2

I'm struggling with the HTML5 native form validation. My understanding from Client-side form validation is you can manually set the validity state of an element with setCustomValidity(). However, this doesn't seem to override any native validation.

For example, if I have a field with required="required" and that field is empty, it is invalid (as expected). If I call setCustomValidity('') on that field, I would expect it to override and set it as valid, but that doesn't happen.

I then thought I could dynamically add novalidate to the field when I want the field to be valid, but if I call checkValidity() after adding novalidate it still returns false. It seems novalidate is only good for allowing the form to be submitted regardless of the fields validity, but the field is still considered :invalid.

Am I missing something, or is this the expected behavior? Also, is there anyway to override any default validations and manually set a field's state to :valid? I would expect something like setValidity(true|false) to be available in the constraint validation API.


A little more context:

I need to toggle a fields constraints based on another fields value. For example, let's say I have the following markup:

<form>
    <div>Has Document?</div>
    <input id="hasDocumentYes" type="radio" value="1" required="required"><label for="hasDocumentYes">Yes</label>
    <input id="hasDocumentNo" type="radio" value="0" required="required"><label for="hasDocumentNo">No</label>

    <label for="documentFile">Document File</label>
    <input id="documentFile" type="file">

    <label for="documentType">Document Types<label>
    <select id="documentType"></select>
</form>

If the user selects "Yes" for "Has Document?", then I want documentFile and documentType to be required. The only working solution I have so far is to dynamically add the required="required" attribute to documentFile and documentType when "Yes" is selected, and then manually call checkValidity().

This works, but it's not ideal. I have lots of these conditional validations that are not always as simple as just required or not required.

Here is the simplified example of the JS I've tried:

// if #documentFile has a required attribute and is empty, the :invalid styles
// are stilled applied after calling setCustomValidity with an empty string
$('#documentFile')[0].setCustomValidity('');

// adding a novalidate dynamically and calling checkValidity() still returns
// false if the field has the required attribute and is empty
$('#documentFile').attr('novalidate', 'novalidate');
$('#documentFile')[0].checkValidity(''); // returns false
TylerH
  • 20,799
  • 66
  • 75
  • 101
patrick3853
  • 1,100
  • 9
  • 17
  • @imvain2 Yes, I am currently adding/removing the `required` attribute dynamically as explained in the question. However, as also explained, this is a simplified example and I have many conditional validations I want to apply (i.e. `min`, `max`, `pattern`, etc.). I am trying to avoid having to write a bunch of custom JS for every form, which is why I was asking if I'm missing something or there's another approach. – patrick3853 Jul 23 '20 at 21:18

1 Answers1

0

I think many of your problems can be solved with the formnovalidate attribute. With that you can override required elements and other restriction on inputs. So with this html:

<input id="documentText" require>

You can have this script make the input valid and invalid:

$('#documentText').prop('formnovalidate', true); //input becomes valid over every other rule
$('#documentText').prop('formnovalidate', false); //input becomes invalid if there are any validations

(BTW: novalidate is meant for the form element and will override all validations of all inputs together.)

As for setCustomValidity: the specs here and here say:

Sets a custom error, so that the element would fail to validate. The given message is the message to be shown to the user when reporting the problem to the user. If the argument is the empty string, clears the custom error.

and

An element can have a custom validity error message defined. Initially, an element must have its custom validity error message set to the empty string.

(Emphasis mine)

So, an input's 'custom error message' can be an empty string, in which case the custom error message has no effect at all on the input. Or, it can be a string that makes the input invalid and that the browser should show to the user.

Klaassiek
  • 2,795
  • 1
  • 23
  • 41