HTML5表单有效的事件监听器

22
  1. HTML5新增了一个"invalid"事件,您可以向其中添加一个监听器:

document.addEventListener('invalid', function(e){
   var element = $(e.target);
   element.addClass("invalid");
   element.parent().addClass("invalid");
}, true);
请注意,这个事件只在提交表单时起作用...如果我给输入框添加样式input:invalid { background: red },当用户开始输入并且其输入无效时就会应用该样式。这个事件只有在提交表单时才触发吗?我尝试将监听器添加到输入框本身而不是文档中,但没有成功。

我添加了一个监听器来应用输入框父元素的样式...现在,当用户更正错误时,它又变成有效了...我知道没有"valid"事件,那么我该怎么实现它呢?

好的,这里有一个示例 --> http://jsfiddle.net/Osoascam/ceArQ/7/ 看起来似乎只有在提交时才会触发无效监听器...我想知道是否有一种方式添加处理程序,就像焦点一样。试试敲一个

提前谢谢,

Óscar


1
说句实话,如果你确实想直接使用无效事件,你也可以通过在输入元素上调用checkValidity()来触发它(如果该输入不合法,则仅会为该输入触发无效事件),或者在表单元素上调用checkValidity()(将为每个不合法的输入触发无效事件)。因此,checkValidity()可以从任何其他事件(例如焦点、模糊、更改等)的事件处理程序中调用,针对该事件目标(输入元素)或其父表单元素,以触发不合法字段的无效事件。 - munsellj
4个回答

20
你应该使用 :invalid 伪类选择器和 input 或 change 事件来解决你的问题。
$(document).bind('change', function(e){
    if( $(e.target).is(':invalid') ){
        $(e.target).parent().addClass('invalid');
    } else {
        $(e.target).parent().removeClass('invalid');
    }
});

这是一个简单的 fiddle:http://jsfiddle.net/trixta/YndYx/

如果您想尽快删除错误类,您应该在更改时添加错误类并在输入事件上删除它(注意:输入事件比建议使用的 keyup 更好,因为它也会在粘贴等操作时触发,但它仅适用于 input 元素,而不是 textarea)。

这里有一个使用输入和更改事件混合的 fiddle: http://jsfiddle.net/trixta/jkQEX/

如果您想在各种浏览器中使用,可以简单地使用 webshims lib 进行 polyfill。这是一个跨浏览器示例: http://jsfiddle.net/trixta/RN8PA/


1
是的,这绝对是正确的方法。非常感谢。我本来以为只有当输入无效时才会触发 $(“#inputBlah”).bind(“invalid”)。 - Óscar

4

由于这些类总是在表单提交时添加,因此在验证之前删除类:

$('#myForm').submit(function(){
    $('.invalid', this).removeClass('invalid'); // Remove all invalid classes
    $(this).removeClass('invalid');             // If the parent = form.
    // Normal validation procedure.
});

期望的结果:

  1. 用户发起 submit
  2. onsubmit 被触发 > 表单中所有 invalid 类名都被移除。
  3. 当需要时,触发 invalid 事件并添加 invalid 类。

更新

在您的 fiddle 中添加了一个额外的块,请参阅更新后的 fiddle:http://jsfiddle.net/ceArQ/10/。我已经实现了 checkValidity() 方法和 validity.valid 属性。现在,当输入无效时,类会自动添加。

document.addEventListener('keyup', function(e){
    var input = e.target;
    if (!$.nodeName(input, 'input')) return;
    input.checkValidity();
    var element = $(input).parent();
    if(input.validity.valid) {
        element.removeClass('invalid');
        element.parent().removeClass('invalid');
    } else { //Remove the lines below if you don't want to automatically add
             // classes when they're invalid.
        element.addClass('invalid');
        element.parent().removeClass('invalid');
    }
});

在松开按键时,会检查输入元素的有效性。如果有效,则从其父元素中删除invalid类。


嗯,是的,但那并不能解决我的问题。如果用户输入无效数据,则会得到“invalid”类,但假设他们没有提交它。相反,他们更正了该字段。因此,表单现在是有效的(input:invalid selector不再适用)。所以问题不在于设置或删除类,而在于知道何时触发事件... - Óscar
这里的代码是错误的。如果表单字段无效,不应触发提交事件。keyup事件不是用于此目的的正确事件。input(或更好的选择是textinput,但支持不太好)事件是正确的事件。 - alexander farkas
@alexanderfarkas 我已经移动了评论并稍微更新了代码,**请参见http://jsfiddle.net/ceArQ/10/**。你的评论意味着什么? - Rob W
实际上,你的代码现在更糟糕了。checkValditiy方法已经返回true/false并且还触发了一个无效事件(这已经被处理了)。所以你不必检查validityState对象,keyup事件也不是正确的事件。用户可以用鼠标将内容粘贴到字段中等等。我为你做了一个fiddle:http://jsfiddle.net/trixta/SMaNM/ - alexander farkas

1

您可以将验证逻辑绑定到 focusblur 事件,或者更加响应地,绑定到 keyup 事件。

$('input').keyup(function() {
    if(isValid(this)) {
        $(this).removeClass('invalid').parent().removeClass('invalid');
        $(this).addClass('valid').parent().addClass('invalid');
    }
    else {
        $(this).removeClass('valid').parent().removeClass('valid');
        $(this).addClass('invalid').parent().addClass('invalid');
    }
});

但我必须自己添加它...那么,难道没有在表单变为有效时触发的事件吗?而且,输入无效时呢? - Óscar
你是指验证逻辑吗?还是事件绑定?因为后者你也需要使用validinvalid事件。老实说,我不明白你想要实现什么...如果你想要一个自定义的有效或无效事件,请尝试这个:http://jsfiddle.net/mAu888/vrZa3/3/ 它会在给定的时间间隔内检查表单是否包含任何:invalid元素。如果有,则触发表单上的自定义invalid事件,您可以在其中注册您的函数。如果表单变为有效,则触发valid事件。请确保将#foo更改为您的表单ID。 - mAu
不,我的意思是这个事件不存在像“click”或“change”那样的形式,因此为了模拟document.addEventListener('invalid')监听器,我必须像你那样在给定的时间间隔内进行检查。如果我没有表达清楚,对不起!再次感谢你! :D - Óscar

1
你尝试过使用:valid来指示字段是否有效,并让无效的表单保持默认样式吗?
然后在提交处理程序中调用form.checkValidity()?(浏览器应该会告诉最终用户哪个表单元素无效)。

1
是的,我尝试过这种方法,但它并不完全满足我的需求,因为输入框的父元素也必须更改,而 CSS 中没有父级选择器 :( - Óscar
@Raynos 如果是 A > B,那么会选择 B 而不是 A。 - thdoan

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