javascript - Why is setCustomValidity('') ignored on input (Chrome 65) - Stack Overflow

Note: to the best of my knowledge this question is not a duplicate question of the following:HTML5: Why

Note: to the best of my knowledge this question is not a duplicate question of the following:

  • HTML5: Why does my “oninvalid” attribute let the pattern fail?
  • HTML5 form required attribute. Set custom validation message?
  • How can I change or remove HTML5 form validation default error messages?

Overview

Given a field that:

  • Has pattern attribute set for validation, for example "[a-f,0-9]{4}" for a 4 character hex string input.
  • Has oninvalid set with setCustomValidity('...some message...') to define a custom validation message
  • Has oninput set with setCustomValidity('') to reset on input

Here is an example showing this:

/* jshint esnext: true */
const form   = document.querySelector("#form");
const field  = document.querySelector("#field");
const output = document.querySelector("#output");

form.addEventListener('submit', (e) => {
  console.log("SUBMIT");
  output.textContent = field.value;
  e.preventDefault(); // Prevent default POST request
});

field.oninvalid = (event) => {
  console.log("INVALID");
  event.target.setCustomValidity('must be valid 4 hex characters');
}

field.oninput = (event) => {
  console.log("INPUT");
  event.target.setCustomValidity('');
}
Output: <span id="output">No output</span>
<form id="form">
  <label for="field">Enter 4 character hex code: </label>
  <input id="field" type="text" pattern="[a-f,0-9]{4}" autoplete=off>
</form>

Note: to the best of my knowledge this question is not a duplicate question of the following:

  • HTML5: Why does my “oninvalid” attribute let the pattern fail?
  • HTML5 form required attribute. Set custom validation message?
  • How can I change or remove HTML5 form validation default error messages?

Overview

Given a field that:

  • Has pattern attribute set for validation, for example "[a-f,0-9]{4}" for a 4 character hex string input.
  • Has oninvalid set with setCustomValidity('...some message...') to define a custom validation message
  • Has oninput set with setCustomValidity('') to reset on input

Here is an example showing this:

/* jshint esnext: true */
const form   = document.querySelector("#form");
const field  = document.querySelector("#field");
const output = document.querySelector("#output");

form.addEventListener('submit', (e) => {
  console.log("SUBMIT");
  output.textContent = field.value;
  e.preventDefault(); // Prevent default POST request
});

field.oninvalid = (event) => {
  console.log("INVALID");
  event.target.setCustomValidity('must be valid 4 hex characters');
}

field.oninput = (event) => {
  console.log("INPUT");
  event.target.setCustomValidity('');
}
Output: <span id="output">No output</span>
<form id="form">
  <label for="field">Enter 4 character hex code: </label>
  <input id="field" type="text" pattern="[a-f,0-9]{4}" autoplete=off>
</form>

Validation works almost as desired, except when the user enters an invalid entry and then proceeds to try and edit it, where their following input states are still invalid:

At this point, neither the custom setCustomValidity message defined in oninvalid is used, nor the empty one defined in onInput.

Instead, as long as the field is in an invalid state and not blurred, the default Please match the requested format. message appears.


Question

What is going on here? Looking at the console, the oninput event is called each time, and therefore event.target.setCustomValidity(''); is called each time.

So why is it that we are still seeing the generic default validation message? Shouldn't setCustomValidity('') disable that?

An acceptable answer here should exhibit the following:

  • The parameter field is respected for validation.
  • Any validation message appears if and only if the user attempts to submit an invalid field and not when they modify the input immediately afterward.
  • The default Please match the requested format. message never appears at all.
Share Improve this question edited Apr 9, 2018 at 0:32 Johannes asked Apr 8, 2018 at 23:25 JohannesJohannes 6,43910 gold badges45 silver badges60 bronze badges 9
  • What browser are you using? I've tested your Bin in Chrome and Safari on a Mac and I cannot reproduce the issue in the animated GIF. The correct message shows and only when the input is invalid – Randy Casburn Commented Apr 8, 2018 at 23:51
  • Chrome on Windows: Version 65.0.3325.181 (Official Build) (64-bit). Chances that this is a bug? – Johannes Commented Apr 8, 2018 at 23:53
  • Yep. Related? stackoverflow./questions/49646085/… – Randy Casburn Commented Apr 8, 2018 at 23:57
  • Seems like it, though their issue is slightly different as their remended workaround (using this pattern attribute) is something I'm already doing. Different use-case, but likely related. – Johannes Commented Apr 8, 2018 at 23:59
  • There was a time early on with Chrome on Windows where the custom validation message would not show without a title attribute. In case you don't know, you can "title" your custom message in some browsers. Try to add a title to the input and see if that changes things. – Randy Casburn Commented Apr 9, 2018 at 0:08
 |  Show 4 more ments

2 Answers 2

Reset to default 6

It appears that this is a bug with Chrome 65 in windows.

using setCustomValidity('') in oninput should disable the default validation messages appearing on input.

The following workaround works for me:

/* jshint esnext: true */
const form   = document.querySelector("#form");
const field  = document.querySelector("#field");
const output = document.querySelector("#output");

const pattern = field.getAttribute("pattern");

form.addEventListener('submit', (e) => {
  console.log("SUBMIT");
  output.textContent = `User submitted: ${field.value}`;
  e.preventDefault(); // Prevent default POST request
});

field.oninvalid = (event) => {
  console.log("INVALID");
  event.target.setCustomValidity('must be valid 4 hex characters');
}

field.oninput = (event) => {
  console.log("INPUT");
  event.target.setCustomValidity('');
  event.target.removeAttribute("pattern");
}

field.onchange = (event) => {
  console.log("CHANGE");
  event.target.setAttribute("pattern", pattern);
}
  Output: <span id="output">No output</span>
  <form id="form">
    <label for="field">Enter 4 character hex code: </label>
    <input id="field" type="text" pattern="[a-f,0-9]{4}" autoplete=off>
  </form>

setCustomValidity is meant to be used when multiple inputs, in bination are invalid. That is why it has to be reset to the empty string manually after. Other wise the title attribute should be used.

Trying to hide the validation error after editing the input is understandable but it is against the HTML5 form philosophy. It is meant to be shown as long as the input is invalid.

Adding maxlength can help the user to not cross the upper limit.

If you really want your bullet points to be satisfied feel free to not use HTML5 form validation but something custom instead.

So the reason a tooltip is shown even when setCustomValidity is set to empty string is because the input element is still invalid as per pattern attribute.

<form id="form">
  <label for="field">Enter 4 character hex code: </label>
  <input id="field" type="text" pattern="[a-f,0-9]{4}" maxlength="4" minlength="4" autoplete="off" title="must be valid 4 hex characters">
</form>

JS

const form   = document.querySelector("#form");
const field  = document.querySelector("#field");
const output = document.querySelector("#output");

form.addEventListener('submit', (e) => {
  console.log("SUBMIT");
  output.textContent = field.value;
  e.preventDefault(); // Prevent default POST request
});

field.oninvalid = (event) => {
  console.log("INVALID");
}

field.oninput = (event) => {
  console.log("INPUT");
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744184126a4562121.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信