jQuery Unobtrusive 客户端验证自定义属性

Posted

技术标签:

【中文标题】jQuery Unobtrusive 客户端验证自定义属性【英文标题】:jQuery Unobtrusive client-side validation of custom attribute 【发布时间】:2014-03-27 00:55:48 【问题描述】:

我创建了一个在服务器端工作的自定义验证属性(在表单发布后),但我无法让验证在客户端工作。

自定义属性为:

public class ReasonableAttribute : ValidationAttribute, IClientValidatable

    public override bool IsValid(object value)
    
        return Approval.IsNumberReasonable(value.ToString());
    

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    
        ModelClientValidationRule rule = new ModelClientValidationRule();
        rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
        rule.ValidationType = "reasonable";
        yield return rule;
    


IsNumberReasonable() 函数只是对输入的字段进行一些检查,以确保他们输入的内容可以合理地是一个批准号(例如,不为空,或“未知”或类似的东西)返回一个 bool true/false

然后我的模型包含:

[Display(Name = "Approval Number"]
[Reasonable(ErrorMessage = "Please enter a reasonable 0")]
public String ApprovalNumber  get; set; 

并且视图包含:

@html.LabelFor(model => model.ApprovalNumber, new  @class = "control-label col-md-3" )
<div class="col-md-9 append field">
 @Html.TextBoxFor(model => model.ApprovalNumber, new  @class = "input text" )
 @Html.ValidationMessageFor(model => model.ApprovalNumber)
</div>

在我尝试添加的 javascript 中:

$.validator.unobtrusive.adapters.addBool("reasonable", "required");
// OR
$.validator.unobtrusive.adapters.add("reasonable");

和:(在 document.ready 之外)

(function ($) 
            $.validator.addMethod('reasonable', function (value, element, params) 
                return value != '';
            , 'Clientside Should Not Postback');
            $.validator.unobtrusive.adapters.addBool('reasonable');
        )(jQuery);

在各种组合中,但未能使其发挥作用。

我有

<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

包含在视图中。

提交表单后,客户端验证适用于其他字段(必填字段等),但 ApprovalNumber 旁边的验证消息永远不会出现/不执行我的自定义验证。

感谢任何指向正确方向的指针。 谢谢。

我也有

<configuration>
  <appSettings>  
   <add key="ClientValidationEnabled" value="true" />
   <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
</configuration>

已经在 Web.config 文件中。

编辑 2: 根据 chenZ 的帖子: 输入字段的html是:

<input class="input text valid" data-val="true" data-val-reasonable="Please enter a reasonable Approval Number" data-val-required="Approval Number is Required." id="ApprovalNumber" name="ApprovalNumber" type="text" value="">

尝试更新我的视图底部:

<script src="~/Scripts/jquery.validate.js"></script>
<script type="text/javascript">
    (function ($) 
        $.validator.addMethod('reasonable', function (value, element, params) 
            return value != '';
        , 'Clientside Should Not Postback');
    )(jQuery);
    </script>

    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/Create.js"></script>

jquery.validate.unobtrusive.js 的结尾现在包含:

    $(function () 
        $.validator.unobtrusive.adapters.addBool('reasonable');
        $("#formID").removeData("unobtrusiveValidation").removeData("validator");
        $jQval.unobtrusive.parse(document);
    );
(jQuery));

create.js 包含:

$.validator.unobtrusive.adapters.addBool("mandatory", "required"); // another custom attribute for checkbox validation
    var v = $("#formID").validate(
        errorClass: "warning",
        onkeyup: false,
        onblur: false,
    );

v 变量被进一步用于提交按钮:

$("#SubmitButton").click(function () 
    if (v.form()) 
          // The form passed validation so continue..
         else 
            // Validation failed, do something else..
        
);

我做了一些进一步的测试,它似乎与以下有关:

(function ($) 
            $.validator.addMethod('reasonable', function (value, element, params) 
                return value != '';
            , 'Clientside Should Not Postback');
        )(jQuery);

当我将其更改为:

(function ($) 
            $.validator.addMethod('reasonable', function (value, element, params) 
                return value != 'unknown';
            , 'Clientside Should Not Postback');
        )(jQuery);

它有效,但只有当我在输入框中键入“未知”时,其他任何东西都会通过.. 同样,如果我输入 return value != 'jhdsfkhsdkfj';,它只会在我输入 jhdsfkhsdkfj 时验证。

所以看起来它正在使用它作为规则?而不是我的服务器端 IsNumberReasonable() 函数。

希望对故障排除有所帮助。

【问题讨论】:

是 $.validator.addMethod 上面的 ref jq.validate.unobtrusive 吗? 不是 100% 确定您的意思。是吗? $.validator.addMethod$.validator.messages 在 JS 的其他地方使用过,所以我认为这就是它的语法.. 【参考方案1】:

我没有尝试过,所以我不确定,但我认为有两个地方你可能错了。

1.rule.ValidationType = "合理"; 检查您的 html,找到输入,是否有 attr data-val-reasonalbe 或 reasonale

$.each(this.adapters, function () 
            var prefix = "data-val-" + this.name,

在 jquery.validate.unobtrusive.js 的第 173 行,你可以找到这个,所以它必须是一个 data-val-xxxx

2.在 jquery.validate.unobtrusive.js 文件末尾可以找到

$(function () 
    $jQval.unobtrusive.parse(document);
);

所以,当页面加载时,所有表单集都验证

这是一件困难的事情。 如果你的代码是这样的

<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
.....
(function ($) 
        $.validator.addMethod('reasonable', function (value, element, params) 
            return value != '';
        , 'Clientside Should Not Postback');
        $.validator.unobtrusive.adapters.addBool('reasonable');
    )(jQuery);

当你做 unobtrusive.parse(document);你的valid方法不存在,adapter也不存在,所以你的formvalid没有一个合理的规则

如果你把代码改成这样

<script src="~/Scripts/jquery.validate.js"></script>
(function ($) 
        $.validator.addMethod('reasonable', function (value, element, params) 
            return value != '';
        , 'Clientside Should Not Postback');
        $.validator.unobtrusive.adapters.addBool('reasonable');
    )(jQuery);
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

有效的方法可以添加,但是$.validator.unobtrusive是未定义的

我认为你应该做更多

<script src="~/Scripts/jquery.validate.js"></script>
(function ($) 
        $.validator.addMethod('reasonable', function (value, element, params) 
            return value != '';
        , 'Clientside Should Not Postback');
    )(jQuery);
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

并把

$.validator.unobtrusive.adapters.addBool('reasonable');

进入 jquery.validate.unobtrusive.js,并确保它在之前运行

$(function () 
    $jQval.unobtrusive.parse(document);
);

我不确定它是否会起作用,也许我会稍后再试。 希望对您有所帮助。

更新 我尝试过这个。 在第2点,您可以使用代码

$(function () 
    $("#formid").removeData("unobtrusiveValidation").removeData("validator");
    $.validator.unobtrusive.parse(document);
);

将此代码放在添加有效方法之后,这将清除有效设置并使用您的自定义规则再次解析

更新 2

$("#a").validate();//first time call is useful
$("#a").validate();//second time call is useless

也到 unobtrusive.parse(...)

jquery.validate.js 第 41 行

var validator = $.data( this[0], "validator" );
if ( validator ) 
    return validator;

和 jquery.validate.unobtrusive.js 第 99 行

result = $form.data(data_validation),
    ...
    if (!result)  ....

&lt;script src="~/Scripts/jquery.validate.unobtrusive.js"&gt;&lt;/script&gt; 这个文件的末尾,称为 unobtrusive.parse(document),它将向表单附加数据。 如果它在您设置代码之前调用,则验证设置没有您的设置。 你可以 removeData(...),然后用你的代码再次运行 unobtrusive.parse(document),就像

<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/setting.js"></script>
<script>
  $(function() $("#formid").removeData(...).removeData(...); 
  ....unobtrusive.parse(document));
</script>

验证插件使用数据名称“validator”和不显眼的使用数据名称“unobtrusiveValidation”。

真的很抱歉我的英语不好,希望你能理解。

【讨论】:

嗨 chenZ,是的,输入确实有 data-val-reasonable 属性。我尝试了您的建议(使用更多信息更新了原始帖子),但它仍然不能 100% 工作。谢谢。 第一次运行 unobtrusive.parse(document) 或运行 $(..).validate(),它将设置数据到表单,下次运行,它检查表单是否有数据,做什么都没有。【参考方案2】:

将此添加到您的 Web.config

<configuration>
  <appSettings>  
   <add key="ClientValidationEnabled" value="true" />
   <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
</configuration>

酷,然后尝试修改您的规则以使用以下规则。

$.validator.unobtrusive.adapters.add("reasonable", ["reasonable"], function (options) 
options.rules["reasonable"] = "#" + options.params.reasonable;
options.messages["reasonable"] = options.message;);

【讨论】:

嗨 Gjohn,您的建议已经存在于 web.config 中。我忘了把它添加到原始帖子中......【参考方案3】:

自从我在调查我的问题时来到这里,我想分享一下,如果您使用任何 3rd 方库进行控件,例如带有选项嵌入客户端库的 DevExpress,那么它们实际上可能会重新包含验证脚本,这可能会导致您的适配器被正确添加,但后来又丢失了。就我而言,我不得不将创建客户端非侵入式验证器适配器的 .js 文件移到这些其他有问题的脚本下方。我还想考虑放弃我自己包含的上述文件,或者将我的 3rd 方库配置为不包含它们,以防止这种混淆。

【讨论】:

以上是关于jQuery Unobtrusive 客户端验证自定义属性的主要内容,如果未能解决你的问题,请参考以下文章

如何使用jQuery unobtrusive和Asp.Net Mvc验证动态生成的单选按钮组?

使用 jquery.validate.unobtrusive 验证复选框

如何使用 jquery unobtrusive 和 Asp.Net Mvc 验证动态生成的单选按钮组?

使用tooltip显示jquery.validate.unobtrusive验证信息

.net MVC内置js验证 jquery.validate.unobtrusive.js重置验证操作(备忘,找了很多次了)

如何在 ASP NET MVC 中自定义不显眼的验证 JQuery 消息?