I use materialize css framework with react and had an issue on <select>
s onChange event propagation.
This way the event is not fired, this.handleSelectChange
is not called.
<select value="B" onChange={this.handleSelectChange}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
When i add the class browser-default
to select
it works pretty well.
<select className="browser-default" value="B" onChange={this.handleSelectChange}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
Not sure if it's a react issue, but maybe.
I also created an issue on materialize repo: https://github.com/Dogfalo/materialize/issues/1160
If you have a repro it would be great.
Is "materialize" perhaps modifying the DOM? It kind of sounds like it, that's a big no-no, you _may_ update styles and props of React managed nodes without errors, but if they're cloned/replaced/moved then it's an invariant error waiting to happen.
I think the guilty's here https://github.com/Dogfalo/materialize/blob/master/sass/components/_form.scss#L654
materialize creates a fake select with a <ul>
as you can see in their demo
There's a lot of DOM mutation happening when you use a materialize custom component, and I guess you'll face similar problems with most of those components. Maybe Material-UI is more suitable for your requirements: http://callemall.github.io/material-ui/
Thank you guys! :)
@bloodyowl You're right, i"ve forgotten that this could be the issue.
@Charca Yes i know about material-ui, i tried it, but materialize felt to be more mature and it has more features. And i hadn't any real issue with it until now. :)
Not an actual React bug so closing out. The fact that materialize is modifying the DOM means you're probably going to have a tricky time of things and you'll probably want to build some wrapper components to make things work better. Good luck!
Yes, but actually your answers helped me, so thanks! :)
this isnt a react answer but materializecss ensures that when the form is submitted, the correct value is sent in the select element so if for instance you have a form (or any container) with id subject_update and the select name is type you can capture the change event with jquery as follows:
$('#subject_update select[name=type]').on('change',function(){console.log('select has changed to:',$(this).val());});
here's a clean way to do it:
componentDidMount() {
// Use Materialize custom select input
$(this.refs.yourSelectTag).material_select(this._handleSelectChange.bind(this));
}
if you're using react < 0.14.0 you'll have to use getDOMNode() on this.refs.yourSelectTag
@davidleverage You made my day! Form with id="subject_update" put me on the right track.
Using delegated event fixes the problem for me.
HTML
<div class="input-field col s10" id="pickerContainer">
<select>
<option value="" disabled selected>Choose your option</option>
</select>
</div>
JS
$('#pickerContainer').on('change', 'select', function(){
console.log("got you");
});
Guys, quick question. When I have dynamic children and need to bind onChangeHandler to each generated "select" component. How can I do this? Seems my ref is not unique and it just binds it to the last in my loop..
Hi @erudinsky I think we can simply use
$("select.dynamicclass").on("change")
handler( by using select element as a prefix ). I just fix my problem in this way.
The element value is always empty for me. The options are generated dynamically, and they do appear in the list, however the node is empty when I inspect it and whatever method I use, the value is not set (i.e. this.refs.selectElement.value
, $(this.refs.selectElement).val()
, this.refs.selectElement.selectedIndex
, etc.)
@zpao many projects use React with Materialize. This is not an isolated case. And I'm not even sure, yet, how Materialize lists all the OPTIONS as they aren't there when I inspect my DOM.... Closing this issue on the basis that "make your own wrapper" in these circumstances is almost insulting.
Closing this issue on the basis that "make your own wrapper" in these circumstances is almost insulting.
@yanickrochon Materialize replaces what React renders outside of React, that is simply not possible to support and thus there's nothing React can fix here. So Materialize is simply incompatible with React, there may be workarounds but I doubt they _truly_ work due to the nature of Materialize, but may just hide the immediate issues and cause errors later.
EDIT: PS. you can always render markup using dangerouslySetInnerHTML
and apply Materialize on that, that is fully supported.
@syranide Well, then, luckily some people do not agree with you, and created react-materialize which seems to solve many issues that "React [can't] fix".
@yanickrochon That's literally what the "make your own wrapper" advice means when it's applied 馃槈
@quannt Man, thanks God I met you here. Thank you for leaving your solution, works great for me. Thanks!
_I've been playing around with Materialize(^0.98.2) select feature with Meteor React. Below is the way how i fixed the issue. Meteor 1.4.4.3 _
import ReactDOM from 'react-dom';
...
componentDidMount(){
$(document).ready(function() {
$('select').material_select();
});
$(ReactDOM.findDOMNode(this.refs.testSelect)).on('change',this.handleSelectChange.bind(this));
}
``
handleSelectChange(event) {
event.preventDefault();
var test = event.target.value;
this.setState({value: test});
}
render(){
...
<div className="input-field col s12">
<select ref="testSelect">
<option value="" disabled selected>Choose your option</option>
<option value="123">Option 1</option>
<option value="223">Option 2</option>
<option value="332">Option 3</option>
</select>
<label>Materialize Select</label>
</div>
}
How can i do @nanda248 's with ref callbacks?
Most helpful comment
here's a clean way to do it:
if you're using react < 0.14.0 you'll have to use getDOMNode() on this.refs.yourSelectTag