避免 jQuery 非侵入式验证中的验证循环

Avoiding validation loop in jQuery unobtrusive validation

提问人:vtortola 提问时间:7/22/2013 最后编辑:Communityvtortola 更新时间:7/27/2013 访问量:534

问:

在我的表单中有两个字段,它们相互比较以查看它们是否有效:

<input type="text" name="StartDate" id="StartDate" value="2"
       data-val="true" data-val-equalto="xx" data-val-equalto-other="EndDate"/>   
<input type="text" name="EndDate" id="EndDate" value="3"
       data-val="true" data-val-equalto="xx" data-val-equalto-other="StartDate"/> 

当我模糊时,也会得到验证。因此,jQuery设法避免了一个与另一个之间的验证循环。StartDateEndDate

现在,我正在尝试在我的自定义验证规则中实现相同的机制。我从“other”字段中获取值,如果一切正常,我也会在“other”中触发验证,但这以验证循环结束:

$.validator.addMethod("customequal-method", function (val, el, p) {
    var $other = $(el).closest('form').find('input[name=' + p.other + ']'); 
    if($other.val() == val){        
        try{$other.valid();}
        finally{return true;}
    }
    return false;
});

我怎样才能应用与jQuery相同的方法?我的意思是,给定这两个字段:

<input type="text" name="StartDate2" id="StartDate2" value="2"
       data-val="true" data-val-customequal="xx xxx" data-val-customequal-other="EndDate2"/>   
<input type="text" name="EndDate2" id="EndDate2" value="3"
       data-val="true" data-val-customequal="xx xx" data-val-customequal-other="StartDate2"/> 

我希望在修改 EndDate2 时,在模糊之后,StartDate2 也会得到验证,并且两者都以与 jQuery 中相同的方式变得有效。

我一直在尝试在 jsFiddle 中组合一个示例,但我无法使我的自定义方法工作: http://jsfiddle.net/vtortola/vu6tm/(如果您发现问题,我将不胜感激),我在jsFiddle中的jQuery不显眼的自定义适配器和方法上启动了一个单独的线程

干杯。

asp.net-mvc-4 unobtrusive-validation unobtrusive-javascript

评论

0赞 Imad Alazani 7/25/2013
因此,在视图模型中,您有开始日期和结束日期,使用 Unobstrusive(自定义验证),您可以验证开始日期和结束日期。右?
0赞 vtortola 7/25/2013
右。这只是两个字段相互比较的示例。这个想法是,例如,在验证 StartDate2 之后,EndDate2 也会得到验证(因为它依赖于 StartDate2,并且它已经更改)。干杯。

答:

1赞 Francesco Abbruzzese 7/27/2013 #1

您需要一个堆栈来了解您返回到以前的 validates 元素。单个值是不够的,因为每个元素都可能涉及其他元素的其他规则。您可以在闭包中定义包含堆栈的 var(isInStack 验证元素是否在数组中):

(function () {
var stack = [];
$.validator.addMethod("customequal-method", function (val, el, p) {
var iAmTheRoot = stack.length == 0;
var $other = $(el).closest('form').find('input[name=' + p.other + ']'); 
if($other.val() == val){        
    try{
      if (!isInStack($other[0]) ) $other.valid();
    }
    finally{
    if (iAmTheRoot) stack = [];
    return true;}
}
return false;
});})();

评论

0赞 vtortola 7/28/2013
但是,对于使用该方法的所有输入和执行,该堆栈变量将共享吗?我需要在方法的第一次调用中创建该堆栈,然后在其余的执行中执行它,但不影响其他字段或规则。
0赞 Francesco Abbruzzese 7/28/2013
不,堆栈不由不同的执行和输入共享,只有包含它的变量被共享,但这不是问题,因为 javascript 没有并行线程,因此该变量由不同的协作输入组在不同的时间间隔内访问。当根输入开始验证时,它从一个空堆栈开始,在对其他验证方法的递归调用返回后,根输入会销毁它使用的堆栈,并将其替换为空堆栈,因此另一个输入可以从空堆栈开始。此外,如果共享可变参数,则不会产生干扰
0赞 Francesco Abbruzzese 7/28/2013
任何其他解决方案都需要重新定义验证器对象方法(这不是 drammatic...我经常这样做)。一个更简单的解决方案是将规则仅应用于两个输入之一,并以这样一种方式进行管理,即更改处理程序附加到第二个输入,每次第二个输入更改时都会触发对第一个输入的验证(我选择此技术来实现连接到其他输入的动态最小和最大规则)。
0赞 vtortola 7/30/2013
它似乎工作正常。让我进一步测试一下:)
0赞 vtortola 7/31/2013
好方法。谢谢!