如何为HTML表单设置自定义验证消息?

453

我有如下HTML表单: http://jsfiddle.net/nfgfP/

<form id="form" onsubmit="return(login())">
<input name="username" placeholder="Username" required />
<input name="pass"  type="password" placeholder="Password" required/>
<br/>Remember me: <input type="checkbox" name="remember" value="true" /><br/>
<input type="submit" name="submit" value="Log In"/>

当前,当我在两个字段都为空时按下enter键,会出现一个弹出框,显示“请填写此字段”。我该如何将默认的消息更改为“此字段不能为空”?

密码字段的错误消息只是*****。要重现此操作,请给用户名赋值并点击提交。


5
为什么不接受浏览器默认的信息呢?这是用户在访问其他网站时看到的信息,如果您创建一个非标准的信息,只会让您的用户感到困惑。(谷歌在确定这个措辞方面可能进行了更多的用户体验评估和测试!) - ChrisV
18
多语言网站怎么处理? - inemanja
3
在我的情况下,在发布之前我想检查该值是否为数字,但是由于某些原因,我不能使用type="number"属性。因此,我将pattern属性设置为检查数字和可选小数点,这将在错误时显示消息“请匹配所请求的格式”。我更希望它说:“你必须给我们一个数字,伙计。” - Kristopher
17个回答

491
这里是一些代码来显示自定义错误消息:
<input type="text" id="username" required placeholder="Enter Name"
       oninvalid="this.setCustomValidity('Enter User Name Here')"
       oninput="this.setCustomValidity('')"/>

这部分很重要,因为它在用户输入新数据时隐藏了错误消息:

oninput="setCustomValidity('')"

注意:在内联事件处理程序中,不需要使用this关键字,但为了保持一致性,您可能仍然想要使用它。

4
请注意,即使在这种情况下您也可以省略 this.,因为内联事件处理程序是在 with(this) 的作用域下运行的(并不是说您应该这样做)。 - phil294

339

使用setCustomValidity

document.addEventListener("DOMContentLoaded", function() {
    var elements = document.getElementsByTagName("INPUT");
    for (var i = 0; i < elements.length; i++) {
        elements[i].oninvalid = function(e) {
            e.target.setCustomValidity("");
            if (!e.target.validity.valid) {
                e.target.setCustomValidity("This field cannot be left blank");
            }
        };
        elements[i].oninput = function(e) {
            e.target.setCustomValidity("");
        };
    }
})

根据@itpastorn在评论中的建议,我已经从Mootools转换为Vanilla JavaScript (示例),但如果需要,您也可以找到相应的Mootools等效方法。

如果setCustomValidity不是空字符串,它将导致该字段被视为无效;因此,在测试有效性之前必须清除它,不能仅仅设置并忘记。

正如@thomasvdb在下面的评论中指出的那样,您需要在invalid之外的某个事件中清除自定义有效性,否则可能会多次通过oninvalid处理程序来清除它。


为什么当我将elements[i]替换为$("#name")时,它不起作用?如果我设置了2个验证,例如type='number' required,我可以为它们设置不同的自定义消息吗? - Lai32290
1
@Lai32290,因为您没有访问实际的DOM对象。$("")返回一个对象数组,即使只有一个对象也是如此。$("")[i]可能是您想要的。 - Noah Passalacqua
1
我并不是在说这段代码好或不好,然而,在HTML5中使用表单验证的目的是为了不需要JavaScript进行表单验证,因此即使对于“纯粹主义者”,使用oninvalid属性也是完全没有意义的。 - John
这对于带有必需属性的输入正常工作。但是对于input type="email"不适用。在输入电子邮件地址的第一个字符后,您会回到标准错误消息“请包括'@'...”我尝试使用else if (e.target.validity.typeMismatch) { e.target.setCustomValidity("My own message")来捕获此问题。没有成功。有什么建议吗? - Mathias Zaja

115

使用 HTML5 事件 oninvalid 很容易控制自定义消息。

以下是代码:

<input id="UserID"  type="text" required="required"
       oninvalid="this.setCustomValidity('Witinnovation')"
       onvalid="this.setCustomValidity('')">

这是最重要的:

onvalid="this.setCustomValidity('')"

3
请检查其他验证,例如模式、最小/最大值等。 http://sanalksankar.blogspot.com/2010/12/custom-validation-message.html - Jaider
10
这会在Firefox中导致一个错误,即刷新时进行验证是成功的,但在更改和修正后则失败。 - Ryan Charmley
12
通过使用onchange="this.setCustomValidity('')",这个 bug 将被解决。请查看下面的答案。 - Salar
8
如果这种方法不起作用(例如在Safari中无效),请改用oninput而不是onvalid - Jimothy
4
@Jimothy对此是正确的,oninput是更通用的解决方案,即使在Chrome中,onvalid也无法正常工作。 - ThisGuyCantEven

71

注意:这种方法在Chrome中已不再起作用,在其他浏览器中未经过测试。请参见下面的编辑内容。此答案仅供历史参考。

如果您认为验证字符串确实不应该由代码设置,您可以将输入元素的title属性设置为“此字段不能为空”。(适用于Chrome 10)

title="This field should not be left blank."

请查看http://jsfiddle.net/kaleb/nfgfP/8/

在Firefox中,您可以添加此属性:

x-moz-errormessage="This field should not be left blank."

编辑

自我回答此问题以来,似乎已经发生了改变。现在添加标题不会更改有效性消息,只会在消息中添加附言。上面的样例仍然适用。

编辑2

从Chrome 51版本开始,Chrome不再使用标题属性。我不确定这个更改是在哪个版本中进行的。


1
我不相信title属性应该是这个最好的位置。也许浏览器应该实现一些其他属性并且达成一致。 - kzh
2
在Firefox中使用声明性错误消息,请使用属性:x-moz-errormessage="此字段不应为空。" - robertc
2
这将在“请填写此字段”下方添加一个描述性消息。 - Magne
@Magne 看起来自我写下这个答案以来已经有所改变。 - kzh

52

使用 HTML5oninvalid 事件非常简单,可以轻松地控制自定义的消息。

以下是代码:

User ID 
<input id="UserID"  type="text" required 
       oninvalid="this.setCustomValidity('User ID is a must')">

8
一旦控件接收到输入,就需要将有效性消息设置为空白,否则第一个执行的有效性消息将会显示在所有字段中。每次调用 setCustomValidity() 时都添加 oninput="setCustomValidity('')"。对Somnath的答案进行加一。 - Tarang

47
通过在正确的时间设置和取消设置setCustomValidity,验证消息将无缺陷地工作。
<input name="Username" required 
oninvalid="this.setCustomValidity('Username cannot be empty.')" 
onchange="this.setCustomValidity('')" type="text" />

我使用了onchange而不是oninputonchange更加通用,无论通过JavaScript还是其他方式改变值时都会触发。

我使用onchange代替oninput,因为onchange更加通用,即使通过JavaScript或其他条件改变值,也会触发事件。


这应该是被接受的答案。在以下浏览器中适用于Windows 10 1709:Chrome 66.0.3359.139 64位,Firefox 59.0.3(64位),Internet Explorer 11.431.16299.0,Edge 41.16299.402.0。在macOS 10.13.2中适用于Safari 11.0(13604.1.38.1.6)。在Android 4.4.4中适用于Chrome 66.0.3359.158。对于那些寻找JSX方式的人:`onInvalid = {(e) => {e.target.setCustomValidity('foo')}} onChange = {(e) => {e.target.setCustomValidity('')}}。 - GuiRitter
附加说明:e 可能为空,例如当从 React Select 字段中删除选项时。不要忘记检查它。 - GuiRitter
勘误:要在React Select中使用此功能,您必须将onChangeonInvalid作为inputProps={{ onInvalid: …, onChange: …, }}传递。 - GuiRitter
1
@EvilJordan 电子邮件此处 - GuiRitter
使用 onchange 而不是 oninput 可以使 HTML5 date 类型字段正常工作。 - mlerley
显示剩余5条评论

43

我创建了一个小型库,以便更轻松地更改和翻译错误消息。您甚至可以按错误类型更改文本,这在Chrome中使用title或在Firefox中使用x-moz-errormessage目前不可用。请到GitHub上查看,并提供反馈。

使用方式如下:

<input type="email" required data-errormessage-value-missing="Please input something">

在 jsFiddle 上有一个演示可用[链接]


36

试试这一个,它更好且经过测试:

    function InvalidMsg(textbox) {
        if (textbox.value === '') {
            textbox.setCustomValidity('Required email address');
        } else if (textbox.validity.typeMismatch){
            textbox.setCustomValidity('please enter a valid email address');
        } else {
           textbox.setCustomValidity('');
        }

        return true;
    }
<form id="myform">
    <input id="email" 
           oninvalid="InvalidMsg(this);" 
           oninput="InvalidMsg(this);"
           name="email"  
           type="email" 
           required="required" />
    <input type="submit" />
</form>

Demo:

http://jsfiddle.net/patelriki13/Sqq8e/


嘿......解决方案不错,但是type=email在Safari浏览器中不起作用。请看http://www.w3schools.com/html/html_form_input_types.asp - Bhawna Malhotra
2
是的,Safari不支持它,但我给出了设置自定义验证消息的答案。 - Rikin Patel

15

我发现最简单和干净的方法是使用数据属性来存储自定义错误。测试节点有效性,并使用一些自定义HTML处理错误。 enter image description here

JavaScript

if(node.validity.patternMismatch)
        {
            message = node.dataset.patternError;
        }

还有一些超级的HTML5

<input type="text" id="city" name="city" data-pattern-error="Please use only letters for your city." pattern="[A-z ']*" required>

4
尽管错误提示只允许字母,但这个模式可以包括空格和撇号。另外,“A-z”还允许使用 “[”,“\”,“]”,“^”,“_”和“`”符号。 - Lawrence Dol

9
防止Google Chrome输入每个符号时出现错误消息的解决方案:

<p>Click the 'Submit' button with empty input field and you will see the custom error message. Then put "-" sign in the same input field.</p>
<form method="post" action="#">
  <label for="text_number_1">Here you will see browser's error validation message on input:</label><br>
  <input id="test_number_1" type="number" min="0" required="true"
         oninput="this.setCustomValidity('')"
         oninvalid="this.setCustomValidity('This is my custom message.')"/>
  <input type="submit"/>
</form>

<form method="post" action="#">
  <p></p>
  <label for="text_number_1">Here you will see no error messages on input:</label><br>
  <input id="test_number_2" type="number" min="0" required="true"
         oninput="(function(e){e.setCustomValidity(''); return !e.validity.valid && e.setCustomValidity(' ')})(this)"
         oninvalid="this.setCustomValidity('This is my custom message.')"/>
  <input type="submit"/>
</form>


乍一看,我以为知道这个为什么会起作用,但是我想不出来。有人能解释一下吗?(立即调用的函数表达式如何改变它?) - Matt - Give Up Github

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接