I am building a simple login page using Google's Material Design Lite web framework and using React.js to handle my UI logic.
I am experiencing a very strange issue: The input text box with floating label works perfectly fine when I render it without React, but doesn't work when rendered through a React class.
My code looks like:
var Login = React.createClass({
render: function(){
return(
<div className="mdl-grid">
<div className="mdl-cell mdl-cell--2-col"></div>
<div className="mdl-cell mdl-cell--8-col">
<form>
<div className="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input className="mdl-textfield__input" type="text" id="sample3" />
<label className="mdl-textfield__label" htmlFor="sample3">Text...</label>
</div>
</form>
</div>
</div>
);
}
});
I have made sure I replace class
with className
and for
with htmlFor
. But it doesn't work, the intended label, never "floats" means it stays within the text box.
When I copy the same code and simply paste it in the HTML, it works fine. (Ofcourse I change the className
and htmlFor
).
What can be the issue? Any help? This is making me nuts.
I am building a simple login page using Google's Material Design Lite web framework and using React.js to handle my UI logic.
I am experiencing a very strange issue: The input text box with floating label works perfectly fine when I render it without React, but doesn't work when rendered through a React class.
My code looks like:
var Login = React.createClass({
render: function(){
return(
<div className="mdl-grid">
<div className="mdl-cell mdl-cell--2-col"></div>
<div className="mdl-cell mdl-cell--8-col">
<form>
<div className="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input className="mdl-textfield__input" type="text" id="sample3" />
<label className="mdl-textfield__label" htmlFor="sample3">Text...</label>
</div>
</form>
</div>
</div>
);
}
});
I have made sure I replace class
with className
and for
with htmlFor
. But it doesn't work, the intended label, never "floats" means it stays within the text box.
When I copy the same code and simply paste it in the HTML, it works fine. (Ofcourse I change the className
and htmlFor
).
What can be the issue? Any help? This is making me nuts.
Share Improve this question asked Oct 3, 2015 at 4:14 Akshay AroraAkshay Arora 1,9451 gold badge16 silver badges31 bronze badges2 Answers
Reset to default 9Although @Kevin E.' s answer is correct, I will post an answer specific to React. According the the official MDL docs,
...in the case where you are creating DOM elements dynamically you need to register new elements using the
upgradeElement
function
The issue is with the way React works. Apparently, it turns out that react does not like when any of its ponents gets mutated outside of it.
MDL tries to mutate all elements with classes mdl-js-*
so as to achieve some dynamic transitions and effects. This mutation must be performed from inside of React, else things won't work.
The proper way to do so is to call upgradeElement
just after React has finished rendering the DOM. Hence the call must be placed in ponentDidMount
and ponentDidUpdate
.
If it is tedious to call upgradeElement
on elements one by one, use upgradeDom
instead. It will upgrade all upgradable elements in the DOM. So the final code would look something like this:
var Login = React.createClass({
loginRequested: function(){
alert('login requested');
},
ponentDidMount: function(){
ponentHandler.upgradeDom();
},
ponentDidUpdate: function(){
ponentHandler.upgradeDom();
},
render: function(){
return(
<div>
<div className="mdl-grid">
<div className="mdl-cell mdl-cell--2-col"></div>
<div className="mdl-cell mdl-cell--8-col">
<div className="mdl-grid">
<div className="mdl-cell mdl-cell--3-col"></div>
<div className="mdl-cell mdl-cell--6-col">
<form onSubmit={this.loginRequested}>
<div className="mdl-textfield mdl-js-textfield mdl-textfield--floating-label make-block">
<input className="mdl-textfield__input" type="text" id="sample3"/>
<label className="mdl-textfield__label" id="label-sample3" htmlFor="sample3">Username</label>
</div>
<div className="mdl-textfield mdl-js-textfield mdl-textfield--floating-label make-block">
<input className="mdl-textfield__input" type="text" id="sample3"/>
<label className="mdl-textfield__label" id="label-sample3" htmlFor="sample3">Password</label>
</div>
<input type="submit" value="Login" className="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent make-block"/>
</form>
</div>
</div>
</div>
</div>
</div>
);
}
});
Had a simular issue today with Ember. The problem is the JS for MDL only initialises on elements already in the DOM.
You can manually 'upgrade' elements with the ponentHandler like this;
<div id="container"/>
<script>
var button = document.createElement('button');
var textNode = document.createTextNode('Click Me!');
button.appendChild(textNode);
button.className = 'mdl-button mdl-js-button mdl-js-ripple-effect';
ponentHandler.upgradeElement(button);
document.getElementById('container').appendChild(button);
</script>
Also, see http://www.getmdl.io/started/ (Use MDL on dynamic websites).
What I'd suggest is handling this upgrade in your React-class. I solved it with a ponent in Ember that renders the textfields / areas / radio buttons and checkboxes for me.
Hopes this helps!