20

I have this input code in my form:

<input maxlength="255" id="information_name" name="information[name]" oninvalid="check(this)" placeholder="Nombre Completo" required="required" size="30" style="width:528px;height:25px;" tabindex="3" type="text">

I change the oninvalid message with this javascritp code:

<script>
 function check(input) {
   if (input.value == "") {
     input.setCustomValidity('Debe completar este campo.');
   } else  {
     input.setCustomValidity('Debe corregir este campo.');
   }

 }
</script>

Here is the problem, if I clicked on submit and the field is empty, the field shome the error so I need to fill the field, but after fill the field, I still getting the warning even the fill is not empty.

What I'm doing wrong???

Jean
  • 5,201
  • 11
  • 51
  • 87

6 Answers6

39

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 take effects of your new input you have to clear the custom validity. Simply you can use the following:

<input required maxlength="255" id="information_name" minlength=1 name="information[name]" oninvalid="setCustomValidity('Should not be left empty.')" 
   oninput="setCustomValidity('')" />

There is no need to use Javascript for this.

taras
  • 6,566
  • 10
  • 39
  • 50
  • 23
    "There is no need to use Javascript for this" - this is Javascript, although inlined in the on... attributes. – stracktracer Jul 04 '15 at 09:11
  • 3
    [Curious turn of phrase you used there](https://stackoverflow.com/a/16878766/8655) – robertc May 24 '17 at 11:08
  • One thing i noticed and I don't know why... why does "test@test" pass? that is not a valid email – carinlynchin Oct 13 '17 at 17:14
  • @carinlynchin according to [HTML5 standard](https://www.w3.org/TR/html52/sec-forms.html#valid-e-mail-address) `test@test` **is valid email**. Regex is `/^[a-zA-Z0-9.!#$%&'*+\/=?^_\`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/`. Last `*` means _any_ number of `.string`s is allowed at the end, including 0. – Sharak Jan 11 '20 at 17:10
9

You can set a custom validity message with setCustomValidity, however any non-blank string will cause the field to act as if it had an invalid value. You need to setCustomValidity('') to clear the invalidated state of the field.

If your validity is simple and controlled via field attributes, you can use object.willValidate to do the test and set the custom validity message:

oninvalid="this.setCustomValidity(this.willValidate?'':'your custom message')"

Erics
  • 803
  • 9
  • 23
  • 3
    willValidate is a property that says whether or not an input can be validated, not if it is valid or not. – gornvix Aug 28 '16 at 19:43
  • 1
    I tried this answer, and it does NOT work. `willValidate` only tells you if the data "can be" validated, not whether it is actually valid or not. Example: Use `` and put a letter in the field (which is invalid) and willValidate is still TRUE. – jsherk Jan 16 '20 at 07:15
3

The issue is that the custom validity error message needs to be reset to blank/empty again, or the field will never validate (even with correct data).

I use oninvalid to set the custom validity error message, and then use onchange to set the message back to default (blank/empty), and then when the form is checked again it will correctly submit if data was corrected, or it will set the custom error message again if there is problem.

So something like this:

<input type="number" oninvalid="this.setCustomValidity('You need to enter an INTEGER in this field')" onchange="this.setCustomValidity('')" name="int-only" value="0" min="0" step="1">
jsherk
  • 6,128
  • 8
  • 51
  • 83
  • Great job! Your answer out of all the answer is the correct answer. This should be set as the best answer. I had a student working on WTForms with Flask framework that was doing a checkbox and was having the same problem. Great job! – wildernessfamily Oct 29 '22 at 03:57
2

If you setCustomValidity to any value that is not the empty string then that will cause the input to be in the invalid state. So your condition is checking for a value, then setting the field to be invalid either way. Only setCustomValidity when the value in the field is actually invalid, otherwise set it to an empty string:

<script>
 function check(input) {
   if (input.value == "") {
     input.setCustomValidity('Debe completar este campo.');
   } else  {
     input.setCustomValidity('');
   }
 }
</script>
robertc
  • 74,533
  • 18
  • 193
  • 177
2

For me only oninvalid="this.setCustomValidity(this.willValidate ? '' :'You must choose the account type from the list')" works. There are lots of issues while using it with IE.

justojas
  • 105
  • 9
0

for React Hooks Typescript users

const inputRef = useRef<HTMLInputElement>(null);

function setCustomValidity(customMsg?: string) {
  inputRef.current?.setCustomValidity(
    typeof customMsg === 'string' ? '' : t.errors.requiredField,
  );
}

<input
  ref={inputRef}
  onInvalid={() => setCustomValidity()}
  onInput={() => setCustomValidity('')}
/>
x-magix
  • 2,623
  • 15
  • 19