Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Onchange event for <select> is not propagated in materialize css when not used with class "browser-default" #3667

Closed
richardsabow opened this issue Apr 14, 2015 · 21 comments

Comments

@richardsabow
Copy link

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: Dogfalo/materialize#1160

@syranide
Copy link
Contributor

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.

@bloodyowl
Copy link
Contributor

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

@Charca
Copy link
Contributor

Charca commented Apr 14, 2015

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/

@richardsabow
Copy link
Author

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. :)

@zpao
Copy link
Member

zpao commented Apr 21, 2015

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!

@zpao zpao closed this as completed Apr 21, 2015
@richardsabow
Copy link
Author

Yes, but actually your answers helped me, so thanks! :)

@davidleverage
Copy link

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());});

@burabure
Copy link

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

@waganse
Copy link

waganse commented Sep 29, 2015

@davidleverage You made my day! Form with id="subject_update" put me on the right track.

@quannt
Copy link

quannt commented Mar 22, 2016

Using delegated event fixes the problem for me.

HTML

`

Choose your option
`

JS

$('#pickerContainer').on('change', 'select', function(){ console.log("got you"); });

@erudinsky
Copy link

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..

@saiponethaaung
Copy link

saiponethaaung commented Jul 3, 2016

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.

@yanickrochon
Copy link

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.)

@yanickrochon
Copy link

yanickrochon commented Aug 13, 2016

@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.

@syranide
Copy link
Contributor

syranide commented Aug 13, 2016

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.

@yanickrochon
Copy link

@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".

@bloodyowl
Copy link
Contributor

@yanickrochon That's literally what the "make your own wrapper" advice means when it's applied 😉

@mcmxc
Copy link

mcmxc commented Sep 14, 2016

@quannt Man, thanks God I met you here. Thank you for leaving your solution, works great for me. Thanks!

@nanda248
Copy link

nanda248 commented Jun 8, 2017

_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>	
}

@hienng
Copy link

hienng commented Jul 5, 2017

How can i do @nanda248 's with ref callbacks?

@eduardoalcantara
Copy link

   <div id="tipo-input" class="input-field col s12 m6">
        <i class="material-icons prefix">content_paste</i>
        <select id="tipo" name="tipo">
           ...
        </select>            
        <label for="tipo">Tipo de Formulário</label>
    </div>


$('#tipo-input').on('change', 'select', function($event) {
    console.log('Changed:', $event.currentTarget.options.selectedIndex);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests