material-design-lite: Required input fields should not be marked invalid (red) automatically.

If an input field is required then it will automatically be marked as invalid. This should not happen on a page load, but once a user interacts with it. See solution below.

/**
   * Check the validity state and update field accordingly.
   *
   * @public
   */
MaterialTextfield.prototype.checkValidity = function () {
    if (this.input_.validity.valid) {
        this.element_.classList.remove(this.CssClasses_.IS_INVALID);
    } else {
        if (this.element_.getElementsByTagName('input')[0].value.length > 0) {
              this.element_.classList.add(this.CssClasses_.IS_INVALID);
        }
    }
};

About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Reactions: 45
  • Comments: 35 (3 by maintainers)

Commits related to this issue

Most upvoted comments

The validation on load should not add is-invalid to any field, seems like a pretty simple fix to me.

GIST

Save the above as a separate js file and include it after material.js. Its basically this pull request in a separate file and will override the default behavior (marking required field invalid) of MaterialTextField.

My solution w/o jQuery (based on the comment of @johnam - thanks dude!) is:

// Check the validity state and update field accordingly.
document.onready = function () {
  document.querySelectorAll("input[data-required]").forEach(function (e) {
     e.required = true;
  });
};

with a input described as:

<input class="mdl-textfield__input" type="text" data-required>

Hi there… Just to check what is with this one?

IMHO, this is pretty unusual behaviour (to mark input with error by default), and as far as i can see (https://www.google.com/design/spec/components/text-fields.html#text-fields-required-fields) material design suggest that input fields should not be marked with error state by default. Correct me if i’m wrong.

When can we expect solution for this problem? I think that 5 months is enough time to fix this tiny problem, don’t you guys think? Is there anything any of us can do?

Another quick workaround: mark your required fields using a data attribute, then add the required property:

$(window).load(function () { $(‘input[data-required=true]’).attr(‘required’, true); });

Hey guys, please check this PR: #4263 Works for me, maybe it will work for you too guys.

For those who are just here for a quick/temporary fix.

$(".mdl-textfield__input").blur(function (){
    if( !this.value ){
        $(this).prop('required', true);
        $(this).parent().addClass('is-invalid');
    }
});
$(".mdl-button[type='submit']").click(function (event){
    $(this).siblings(".mdl-textfield").addClass('is-invalid');
    $(this).siblings(".mdl-textfield").children(".mdl-textfield__input").prop('required', true);
});

Make sure all your fields don’t have a required tag by default.

Hi guys. I’m a newbie and it’s likely my solution is not the best one but here it comes: I’m using RoR (Rails 5) and if I delete require:true from the form (I require the data on the model validations), the input is still being required before submitting but Material Design doesn’t add the is-invalid class

We are going to work on getting V2 details finalized and announced. Once we have the components as they exist now upgraded we can address how to best handle this situation with V2’s structure.

There are a few different options here each with their own set of benefits and drawbacks. It will be best to move forward on this once we can show functioning code to see exactly how it will work in applications.

Agreed having a required input field add warning classes to the element on page load is not desirable. Its cool that MDL is handling this, but I would actually prefer if it just simply provided the css classes for me. Then I could simply apply these validation states using whatever change detection system i’m using, in my case Angular.

@d4nd As explained before, we unfortunately don’t have a clean way of achieving this directly in MDL. Any of the solutions shared above will probably do the trick, though!

Here’s another solution that utilizes jQuery.

Example HTML (note the data-required):

<form>
  <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
    <input class="mdl-textfield__input" pattern="[A-Z,a-z, ]*" type="text" id="name" name="name" data-required>
    <label class="mdl-textfield__label" for="name">Name</label>
    <span class="mdl-textfield__error">Please enter your name.</span>
  </div>
  <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
    <textarea class="mdl-textfield__input" type="text" id="message" name="message" data-required></textarea>
    <label class="mdl-textfield__label" for="message">Message</label>
    <span class="mdl-textfield__error">Please enter a message.</span>
  </div>
  <p>
    <button class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent" type="submit" id="submit">Submit</button>
  </p>
</form>

JavaScript:

$(function() {
  componentHandler.registerUpgradedCallback('MaterialTextfield', function(textfield) {
    var input = $(textfield).find('.mdl-textfield__input');
    if (input.data('required') != null) input.attr('required', true);
  });
});

Here is my solution, work with original required attribute, any advice is welcome.

//  push it to array and remove required attribute
let requiredComponents = document.querySelectorAll("[required]");
requiredComponents.forEach(function(e){
  e.removeAttribute('required');
})
// when submit button click, add required attribute back
document.getElementById("submit-button").addEventListener("click", function(){
  requiredComponents.forEach(function(e){
    e.setAttribute('required', true)
  })
});
// also when form submit event
document.getElementById("form-id").addEventListener("submit", function(){
  requiredComponents.forEach(function(e){
    e.setAttribute('required', true)
  })
});
// you can also add required attribute back when any other event, like blur...etc.

@dannymcpherson As long as you are not requiring the field to be submitted that will work. What about when someone loads the page and just presses submit without changing or making any inputs active?

I fixed it in my change handler (react-mdl):

<Textfield
  type="password"
  label="Password"
  pattern=".{6,20}"
  error="password must contain between 6 and 20 characters"
  floatingLabel
  onChange={(e) => {e.target.required = true}}
/>

Totally agree, if someone should put is-invalid class that should display error state, but in case where there is no error class and input is empty (we can consider this as a clean input by default) then we don’t need error state.

For now, i solved this problem by hacking the css, but this is not long-term solution for me.

I’ll see what i can do about this one.