0

I seem to have an issue with HTML5 Form Validation. When I set the custom error message the pattern seems to be incorrect and the field won't validate...

Form

<form action="{PHP_SELF}" method="post" id="register-form" class="register-form">
    <div class="">
        <label for="username">Username</label>
        <input type="text" name="username" id="username"
               value=""
               pattern="^[a-zA-Z0-9\s]{3,20}$"
               required
               data-custom-error="Username can only contain characters and numbers and must be between 3 - 20 characters.">
    </div>
</form>

JavaScript:

(function() {
    let inputs = document.querySelectorAll("#register-form div input");

    for (let input in inputs) {
        if(inputs.hasOwnProperty(input)) {
            let current = inputs[input];

            current.setCustomValidity(current.dataset.customError);

        }
    }
})();
Martyn Ball
  • 4,679
  • 8
  • 56
  • 126

1 Answers1

0

From what I understand, setCustomValidity internally sets the validity of the input but does not actually trigger a UI update to reflect it (I think it waits for the submit event to happen). You can manually trigger it by calling reportValidity on the form.

Related SO Question

(function() {
  let form = document.querySelector('form');
  let inputs = document.querySelectorAll("#register-form div input");

  for (let input in inputs) {
    if (inputs.hasOwnProperty(input)) {
      let current = inputs[input];
      current.setCustomValidity(current.dataset.customError);

    }
  }
  form.reportValidity();
})();
<form action="{PHP_SELF}" method="post" id="register-form" class="register-form">
  <div class="">
    <label for="username">Username</label>
    <input type="text" name="username" id="username" value="" pattern="^[a-zA-Z0-9\s]{3,20}$" required data-custom-error="Username can only contain characters and numbers and must be between 3 - 20 characters.">
  </div>
</form>

EDIT: Based on the discussion in the comments:

function validate(el){
  var form = document.querySelector('form');
  var reg = new RegExp(el.dataset.r);
  if(reg.test(el.value)){
    el.setCustomValidity('');
  }else{
    el.setCustomValidity(el.dataset.errorMessage)
  }
  form.reportValidity();
}
<form>
<input type="text" name="username" onkeyup="validate(this)" data-r="^[a-zA-Z0-9\s]{3,20}$" data-error-message="Invalid Input" />
</form>
Chirag Ravindra
  • 4,760
  • 1
  • 24
  • 35
  • this code snippet is not working on my end (Chrome Win10) – Domenik Reitzner Apr 10 '18 at 11:01
  • That is curious.. It should work on Chrome. Can you test by clicking on `Run Code Snippet` button below the code in the answer? Does it throw an error? You can also look at the link I have shared in the question which offers a polyfill for `reportValidity` on browsers which do not support it – Chirag Ravindra Apr 10 '18 at 11:03
  • Yep, clicked `Run Code Snipped`, but validation never passes. I get the message on every `onkeyup`-Event – Domenik Reitzner Apr 10 '18 at 11:32
  • Ah. Yes. That is the expected behaviour. The normal procedure is to run validation and call `setCustomValidity('')` with an empty string to indicate no errors. The example sets it to a string to demonstrate the error condition – Chirag Ravindra Apr 10 '18 at 11:35
  • 1
    My recommendation is to move the regexp out of the markup attribute and into the function. Based on the result of matching the regexp, you can either call `setCustomValidity' with an empty string or an error message – Chirag Ravindra Apr 10 '18 at 11:37