Почему setCustomValidity ('') игнорируется при вводе (Chrome 65)

Примечание: насколько мне известно, этот вопрос является нет дублирующим вопросом следующего:


Обзор

Учитывая поле, которое:

  • Имеет атрибут pattern, установленный для проверки, например "[a-f,0-9]{4}" для ввода 4-х символьной шестнадцатеричной строки.
  • Имеет oninvalid, установленный с setCustomValidity('...some message...') для определения настраиваемого сообщения проверки
  • oninput установлен с setCustomValidity('') для сброса на входе

Вот пример, показывающий это:

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

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

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

field.oninput = (event) => {
  console.info("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}" autocomplete=off>
</form>

Проверка работает почти так, как хотелось бы, за исключением случаев, когда пользователь вводит недопустимую запись, а затем пытается ее отредактировать, при этом следующие состояния ввода все еще недействительны:

Почему setCustomValidity (&apos;&apos;) игнорируется при вводе (Chrome 65)

На этом этапе не используется ни пользовательское сообщение setCustomValidity, определенное в oninvalid, ни пустое сообщение, определенное в onInput.

Вместо этого, пока поле находится в недопустимом состоянии и не размыто, отображается сообщение Please match the requested format. по умолчанию.


Вопрос

Что здесь происходит? Глядя на консоль, каждый раз вызывается событие oninput, и поэтому каждый раз вызывается event.target.setCustomValidity('');.

Так почему же мы все еще видим общее сообщение проверки по умолчанию? Разве setCustomValidity('') не должен это отключать?

Приемлемый ответ здесь должен показывать следующее:

  • Поле parameter используется для проверки.
  • Любое сообщение проверки появляется тогда и только тогда, когда пользователь пытается отправить недопустимое поле, а не тогда, когда они изменяют ввод сразу после этого.
  • Сообщение Please match the requested format. по умолчанию никогда не появляется.

Какой браузер вы используете? Я протестировал вашу корзину в Chrome и Safari на Mac, и я не могу воспроизвести проблему в анимированном GIF. Отображается правильное сообщение и только тогда, когда ввод недействителен

Randy Casburn 09.04.2018 01:51

Chrome в Windows: Version 65.0.3325.181 (Official Build) (64-bit). Вероятность того, что это ошибка?

Johannes 09.04.2018 01:53

Ага. Связанный? stackoverflow.com/questions/49646085/…

Randy Casburn 09.04.2018 01:57

Похоже, что это так, хотя их проблема немного отличается, поскольку их рекомендуемый обходной путь (с использованием этого атрибута шаблона) - это то, что я уже делаю. Другой вариант использования, но, вероятно, связанный.

Johannes 09.04.2018 01:59

Было время, когда Chrome в Windows работал рано, когда пользовательское сообщение проверки не отображалось без атрибута title. Если вы не знаете, вы можете «назвать» свое собственное сообщение в некоторых браузерах. Попробуйте добавить заголовок к вводу и посмотрите, изменится ли это.

Randy Casburn 09.04.2018 02:08

Интересно. Он добавляет заголовок под сообщением по умолчанию всякий раз, когда он его показывает. Не то, что мне здесь нужно, но полезно знать!

Johannes 09.04.2018 02:10

Да ... сообщите об ошибке или выполните резервное копирование браузера.

Randy Casburn 09.04.2018 02:12

Выяснил обходной путь. удаление атрибута pattern в oninput и повторное добавление его в onchange дает мне желаемое поведение.

Johannes 09.04.2018 02:19

Рад, что ты разобрался! Потрясающие.

Randy Casburn 09.04.2018 02:26
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
9
2 840
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже, что это ошибка Chrome 65 в Windows.

использование setCustomValidity('') в oninput должно отключить сообщения проверки по умолчанию, появляющиеся при вводе.

Для меня работает следующий обходной путь:

/* 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.info("SUBMIT");
  output.textContent = `User submitted: ${field.value}`;
  e.preventDefault(); // Prevent default POST request
});

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

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

field.onchange = (event) => {
  console.info("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}" autocomplete=off>
  </form>

setCustomValidity предназначен для использования, когда несколько входов в комбинации недопустимы. Поэтому после этого необходимо вручную сбросить его на пустую строку. В противном случае следует использовать атрибут title.

Попытка скрыть ошибку проверки после редактирования ввода понятна, но противоречит философии формы HTML5. Он предназначен для отображения до тех пор, пока введенные данные недействительны.

Добавление максимальной длины может помочь пользователю не переступить верхний предел.

Если вы действительно хотите, чтобы ваши пункты списка были удовлетворены, не стесняйтесь использовать проверку формы HTML5, а вместо этого использовать что-то индивидуальное.

Таким образом, всплывающая подсказка отображается, даже если для setCustomValidity задана пустая строка, потому что элемент ввода все еще недействителен в соответствии с атрибутом шаблона.

<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" autocomplete = "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.info("SUBMIT");
  output.textContent = field.value;
  e.preventDefault(); // Prevent default POST request
});

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

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

Другие вопросы по теме