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.
Although @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 components 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 componentDidMount
and componentDidUpdate
.
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');
},
componentDidMount: function(){
componentHandler.upgradeDom();
},
componentDidUpdate: function(){
componentHandler.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>
);
}
});