首页 > 解决方案 > 是否有 HTML5 验证 API 将元素的状态设置为无效?

问题描述

我不想使用 HTML 5 验证 API,但为了一件事。我将使用 JavaScript 进行自定义验证,但我想使用漂亮的工具提示,比如浏览器用来显示验证消息的东西。

所以,简而言之,我想有选择地element.setCustomValidity("my own message")在我自己的事件处理程序中使用,这样我就可以避免使用第三方工具提示。

但是,即使我设置了自定义有效性,它也不会显示,直到我以某种方式使控件的状态无效

如果我调用验证 API ( element.checkValidity()),它将开始进行自己的内置验证,以查找我的 HTML 元素的属性。但我不想要这些。

function submitEventHandler() {
  let errors = myOwnValidateFunction();

  if (errors && errors.length > 0) {
     let txt = document.getElementById("txt");
     txt.setCustomValidity("No, no, no, no, you're doing it wrong!");

    // Is there a way to invalidate an HTML element?
    // ...???

  }
}

标签: javascripthtml

解决方案


好吧,和往常一样,每个浏览器在几乎任何新 API 上的行为都不同。

要使输入无效,设置 this: 就足够了input.setCustomValidity('just an error');,这会让浏览器知道这个输入有问题。

但是每个浏览器都会做自己的事情:

Chrome - 在您尝试提交表单之前不会显示任何错误,只会让用户知道一个有错误的字段有错误,它会忽略其余有错误的输入。

Firefox - 将在您设置后立即显示您的自定义消息并以红色突出显示输入,您无需等待提交即可显示错误,单击提交时会在无效输入上显示不同的工具提示。

Edge - 仅在用户将鼠标悬停在其上时才会显示带有自定义消息的工具提示,并在提交后以不同的工具提示突出显示

没有在其他浏览器上测试过,但我相信每个浏览器都会使用自己的方式来显示错误,有些可能会等待提交,有些会立即显示,但所有支持此 API 的人都应该在你之后使输入无效input.setCustomValidity('Some error message')

这就是为什么您可能会考虑显示自己的工具提示以避免这种浏览器依赖性,并确保它在所有这些上都以相同的方式工作。

https://jsfiddle.net/q60bwteL/17/

更新

您不需要设置任何类型,并且上面的验证对 的工作方式相同type='text',我不确定您会看到什么,但下面的代码片段有 2 个输入,1 个没有类型,1 个有type='text',两者都有效。

您可以为您的问题创建一个小提琴,以便我看一下,但正如您从小提琴中看到的那样,它适用于所有类型的输入: https ://jsfiddle.net/q60bwteL/21/

但同样,请注意,它在不同浏览器上的工作方式不同,chrome 仅显示第一个有错误的字段,而不是所有字段,仅在提交时显示,而 firefox 显示所有字段的错误(如果有多个错误)并且在您单击之前在提交。

这就是为什么我个人从不相信用我自己可以做的事情来实现浏览器的原因,实现基本的错误处理非常容易,从你已经拥有的问题来看,你只需要添加样式和工具提示,有很多方法可以在 Web 上单独使用 CSS 创建工具提示(例如:https ://stackoverflow.com/a/25391104/8727608 )。

创建一个函数来处理你的错误:

function setError(inputElement, errorMessage) {
  inputElement.setAttribute('title', 'errorMessage');
  inputElement.classList.add('errorInput') 
}

创建一个将删除所有错误内容的函数:

function removeError(inputElement) {
  inputElement.removeAttribute('title');
  inputElement.classList.remove('errorInput') 
}

并根据需要使用 CSS 设置 errorInput 类的样式。

现在我假设您只返回带有错误消息的字符串数组中的错误,但是您可以使用一个对象数组,每个对象都包含错误消息和有错误的输入元素:

if (errors && errors.length > 0) {
  for(var i = 0; i<errors.length; i++) {        
    setError(errors[i].element, errors[i].message);
  }
}

在验证输入之前,只需调用 removeError 函数,如果有错误,请不要忘记在提交时返回 false。(就像你已经做的那样)

更新 2

我不知道为什么我没有想到。但是有一种方法可以停止验证并在需要时启动它:

在表单上添加novalidate属性会让浏览器知道您不想在该表单上执行验证,因此这不会显示任何错误,并且会按照您的喜好处理提交。

但是您仍然想使用该验证,为此您可以在表单元素上调用reportValidity(),基本上这个函数启用提交验证,不管你在哪里调用它,它会在提交时运行验证单击但是这将仅显示带有错误消息的第一个输入,而不是所有输入(即使在 firefox 上),看起来有 2 种验证状态,提交之前和之后,不知道为什么,但这是 2 种不同的检查,并且您只能控制提交后检查,而不是之前。

检查这个小提琴:https ://jsfiddle.net/q60bwteL/64/

所以你可以控制你什么时候做验证,但是有两种验证,提交前和提交后,你只能在提交后控制,它只显示第一个输入错误而不是全部。我们喜欢吗?不,为什么会这样?老实说,我不知道,看起来firefox开发人员在发现第一个错误后只是简单地打破了循环。

PS - 想了想,他们只是简单地实现了 title 属性的 tooltip 方法,但是因为只有 1 个元素可以悬停或聚焦,所以只能显示 1 条错误消息,这就是 tooltips 的工作方式。


推荐阅读