Why does my "oninvalid" attribute let the pattern fail?

This little HTML5 password field works perfectly WITHOUT the oninvalid attribute (the pattern say: minimum 6 characters):

<form>
    <input type="password" name="user_password_new" pattern=".{6,}" required />      
    <input type="submit"  name="register" value="Register" />
</form>

See the jsFiddle here.

But when I add an oninvalid attribute that gives out a custom error message when user's input does not fit the pattern, the entire field NEVER becomes valid, see the code here:

<form>
    <input type="password" name="user_password_new" pattern=".{6,}" oninvalid="setCustomValidity('Minimum length is 6 characters')" required />      
    <input type="submit"  name="register" value="Register" />
</form>

See the jsFiddle here.

Can you spot the mistake ?


If you set a value with setCustomValidity() then the field is invalid. That is setting a non-zero length string causes the browser to consider the field invalid. In order to allow for the effects of any other validations you have to clear the custom validity:

<input type="password" name="user_password_new" pattern=".{6,}" required
   oninvalid="setCustomValidity('Minimum length is 6 characters')" 
   oninput="setCustomValidity('')" />

Since I stumbled on the same problem, here is my solution – tested and working with FF, Chrome, IE 10, Edge (Feb 2017).

<form>
<input pattern="1234" oninput="setCustomValidity(''); checkValidity(); setCustomValidity(validity.valid ? '' :'please enter 1234');">
<input type="email" required>
<input type="submit">
</form>

Explanation:

setCustomValidity(''); removes the custom error string which otherwise would always result in an invalid field at the validation process.

checkValidity(); does a manual validation – the same as it is happening at the form submisson. The result is stored in validity.valid.

The second setCustomValidity(validity.valid ? '' :'please enter 1234'); now sets the error string according to the validation result. If the field is valid it needs to be empty, otherwise the custom error string can be set.


I like to use like this:

<input type="email" name="Email" required oninvalid="setCustomValidity('ErrorMessage')"/>

And unplugged for all of valid input data

UPD, one more thing for better work:

    $("input").attr("onblur", "setCustomValidity('')");
    $("input").attr("oninput", "setCustomValidity(' ')");