material-design-lite
material-design-lite copied to clipboard
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);
}
}
};
i have update to the latest still bug? have been commited ? thansk rzr999 for given choice.
@alien3d Since the issue is still open, this has not been fixed. @rzr999 had been working on a PR (#1503), you can see the previous attempt and progress there. As stated there, we have to sync with the MD team first.
Maybe I'm missing something here, but what if the error styling was only applied under the :focus pseudo class? That would avoid the need for any sort of state tracking and would provide adequate feedback to the user.
Applying only under focus would then mean it always would only show when focused. This is certainly not desirable since you need to be able to display invalid input at any arbitrary time.
We need to touch base with the spec team and see if we can get the spec changed to align with what the web currently provides natively (which is the same setup we currently have.) Otherwise, we need to dig into dirty state management more which is a PITA.
Ok, I take your point. But I really think the current behavior is undesirable...
The current behavior is exactly what browsers provide by default. Which is why we should emulate it imo. There is discussion going on of an intermediate pseudo state to address this in browsers, but afaik no one has it implemented yet.
If you want different behavior now, it may be best to not use our provided JS and build your own component that handles the advanced dirty state checking.
@liddellj: see our discussion on this topic and the last pull request on ticket #1503 as @surma suggested. It's a quick hack which doesn't respect server-side validation but it might suit your needs. I am looking into the pseudo state solution.
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?
We do not currently have a clean way of handling state checking and server-side validation use-cases. If someone puts is-invalid onto a textfield to show it has an error, we should respect that. Not ignore it since there is no length of input.
We need a method that handles existing invalid targeting while still not appearing on startup if something is invalid but not targeted manually, and it needs to not cause BC concerns. If anyone has an idea to that, please let us know or even send in a Pull Request.
Once again, as to the specification alignment this is a known deviation in 1.x. However it is the platforms native API we are taking advantage of where the current specification is built android-platform first and web-second.
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.
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.
The validation on load should not add is-invalid to any field, seems like a pretty simple fix to me.
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.
Hey guys, please check this PR: #4263 Works for me, maybe it will work for you too guys.
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); });
Has anyone tried PR #4263? Still working just as expected for me.
#4263 works great for me. Is there a reason it's not merged yet?
It is considered a BC break to change this functionality. So even if we do accept it into master it will go into V2 and not be introduced to the 1.x line.
I am considering our options with that being the case as to whether we want to simply introduce our own dirty state management in 2 to handle this with greater detail.
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.
Assigning to Travis and Sergio to keep this in mind when developing the V2 components. It is spec-aligning, however I would discuss with the team the way the web natively works and see if the spec could be adjusted to account for this here.
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>
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}}
/>
@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?
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.
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);
});
});
There is no update regarding the issue?
@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!
@sgomes Thank you very much for the quick feedback. I'll try out some of them.
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.
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