Search code examples
javascripthtmlreactjsmaterial-design-lite

Issue while rendering MDL text field with React.js


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.


Solution

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