【问题标题】:MVC unobtrusive validation on checkbox not working复选框上的 MVC 不显眼验证不起作用
【发布时间】:2011-10-18 21:38:21
【问题描述】:

我正在尝试实现this post 中提到的代码。换句话说,我正在尝试在条款和条件复选框上实施不显眼的验证。如果用户没有选择复选框,那么输入应该被标记为无效。

这是我添加的服务器端验证器代码:

/// <summary>
/// Validation attribute that demands that a boolean value must be true.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }
}

这是模型

[MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }

这是我的看法:

@Html.EditorFor(x => x.AcceptTermsAndConditions)
@Html.LabelFor(x => x.AcceptTermsAndConditions)
@Html.ValidationMessageFor(x => x.AcceptTermsAndConditions)

这是我用来附加验证器客户端的 jQuery:

$.validator.unobtrusive.adapters.addBool("mustbetrue", "required");

但是,客户端脚本似乎没有启动。每当我按下提交按钮时,其他字段的验证都会正常启动,但条款和条件的验证似乎没有启动。这是我单击提交按钮后代码在 Firebug 中的外观。

<input type="checkbox" value="true" name="AcceptTermsAndConditions" id="AcceptTermsAndConditions" data-val-required="The I confirm that I am authorised to join this website and I accept the terms and conditions field is required." data-val="true" class="check-box">
<input type="hidden" value="false" name="AcceptTermsAndConditions">
<label for="AcceptTermsAndConditions">I confirm that I am authorised to join this website and I accept the terms and conditions</label>
<span data-valmsg-replace="true" data-valmsg-for="AcceptTermsAndConditions" class="field-validation-valid"></span>

有什么想法吗?我错过了一步吗?这让我欲罢不能!

提前致谢 S

【问题讨论】:

  • 您不能只使用[Requred] 属性而不是创建自己的MustBeTrueAttribute 吗?

标签: asp.net-mvc-3 razor unobtrusive-javascript unobtrusive-validation


【解决方案1】:

您需要在自定义属性上实现IClientValidatable,以便将您在客户端注册的mustbetrue 适配器名称与此属性绑定:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType = "mustbetrue"
        };
    }
}

更新:

完整的工作示例。

型号:

public class MyViewModel
{
    [MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
    [DisplayName("Accept terms and conditions")]
    public bool AcceptsTerms { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

查看:

@model MyViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
    $.validator.unobtrusive.adapters.addBool("mustbetrue", "required");
</script>

@using (Html.BeginForm())
{
    @Html.CheckBoxFor(x => x.AcceptsTerms)
    @Html.LabelFor(x => x.AcceptsTerms)
    @Html.ValidationMessageFor(x => x.AcceptsTerms)
    <input type="submit" value="OK" />
}

【讨论】:

  • 我虽然你有它丹恩(你肯定让我走得更远),但它仍然无法在客户端工作。 javascript正确吗? $.validator.unobtrusive.adapters.addBool("mustbetrue", "required");
  • 丹恩 - 我已经完成了所有这些,但我仍然无法让我的示例正常工作。问题是输入的 HTML 无论如何都保持不变(尽管现在出现了 data-val-mustbetrue ,但请参阅原始问题中的 html!)。无论如何,data-val 始终设置为 true - 即使在页面加载时也是如此。这是你所期望的吗?我什至将我的 javascript 更改为 $.validator.unobtrusive.adapters.addBool("mustbetrue");而且我仍然在 HTML 中获得 data-val-required 属性,这是我没想到的......有什么想法吗?
  • @Sniffer,您将获得 data-val-required 属性,因为您的 AcceptsTerms 属性是不可为空的布尔属性,因此 ASP.NET MVC 会自动附加它。这是预期的行为。
  • 效果很好!为了在客户端使用本地化错误消息(带有ErrorMessageResourceTypeErrorMessageResourceName)而不是默认的必需消息,我不得不将属性定义中的一行更改为ErrorMessage = FormatErrorMessage(metadata.DisplayName),
  • 只是在此处添加的有用信息。这条线 $.validator.unobtrusive.adapters.addBool("mustbetrue", "required"); 必须像 Dimitrov 一样添加到 &lt;script type="text/javascript"&gt; 中。例如,如果您将它添加到 $(document).ready(function () { 中,它将不起作用。而且您不需要在 jquery.validate.unobtrusive 文件中添加任何内容。
【解决方案2】:

嗅探器,

除了实现达林的方案外,还需要修改jquery.validate.unobtrusive.js文件。在这个文件中,你必须添加一个“mustbetrue”的验证方法,如下:

$jQval.addMethod("mustbetrue", function (value, element, param) {
    // check if dependency is met
    if (!this.depend(param, element))
        return "dependency-mismatch";
    return element.checked;
});

那(我一开始忘了加这个),你还要在jquery.validate.unobtrusive.js中加上以下内容:

adapters.add("mustbetrue", function (options) {
    setValidationValues(options, "mustbetrue", true);
});

辅导员

【讨论】:

  • 这太棒了,我错过了什么!杰出的。希望我能把你和达林都标记为答案,但当你让我越过终点线时,你就明白了!最后一个问题来整理一下 - 有没有一种方法可以添加这 2 段代码而无需更改核心 unobtrusive.js 脚本?我尝试将 $jQval.addMehod 更改为 $.validator.addMethod 并将 adapters.add 更改为 $.validator.unobtrusive.adapters.add 并从外部脚本文件调用它们,但这似乎不起作用。有什么想法吗?
  • 啊,抱歉——我有点跑题了。它不太好用。如果未选中复选框,则验证现在显示为错误(太好了!),但如果用户随后检查复选框(不好!),验证仍然显示为无效。这现在正在阻止页面发回,因为它认为仍然存在错误。有什么想法吗?
  • @Sniffer,对不起,但是当我认为我很狡猾并且不要仔细检查时,就会发生这种情况。行“返回 this.checked;”是不正确的,我已经改变了。我尝试了几种方法将脚本插入页面,而不是修改jquery.validate.unobtrusive.js,但都没有成功。
  • 我可以吻你(但我显然不会)! element.checked 是一种享受!很奇怪,如果不直接更改 jquery.validate.unobtrusive.js 就无法添加脚本。我会再玩一些 - 也许值得单独提出一个问题。无论如何,如果我找到办法,我会在这里发布更新。再次感谢!
  • 我正在使用$.validator.addMethod()$.validator.unobtrusive.adapters.add() 在外部添加自定义验证器。
【解决方案3】:

我不确定为什么这对我不起作用,但我选择使用您的代码并做一些稍微不同的事情。

在我的 JavaScript 加载中,我添加了以下内容,如果您选择复选框并取消选中它,这会使复选框触发不显眼的验证。另外,如果您提交表格。

$(function () {
        $(".checkboxonblurenabled").change(function () {
            $('form').validate().element(this);
        });
});

您还需要将 CSS 类添加到您的复选框中,就像这样。

@Html.CheckBoxFor(model => model.AgreeToPrivacyPolicy, new { @class = "checkboxonblurenabled"})

所以,我们现在需要连接模型并放入类来处理服务器端验证(我正在从上面重复使用)但稍微改变不显眼。

这是扩展 IClientValidate 的客户属性,如上例所示...

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType = "mustbetrue"
        };
    }
}

在您的模型中,对象属性设置所需的属性符号

 [MustBeTrue(ErrorMessage = "Confirm you have read and agree to our privacy policy")]
    [Display(Name = "Privacy policy")]
    public bool AgreeToPrivacyPolicy { get; set; }

好的,我们已准备好放入 JavaScript。

(function ($) {
    /*
    START CHECK MUST BE TRUE - UNOBTRUSIVE JAVASCRIPT
    START CHECK MUST BE TRUE - UNOBTRUSIVE JAVASCRIPT
    START CHECK MUST BE TRUE - UNOBTRUSIVE JAVASCRIPT
    */
    jQuery.validator.unobtrusive.adapters.add("mustbetrue", ['maxint'], function (options) {
        options.rules["mustbetrue"] = options.params;
        options.messages["mustbetrue"] = options.message;
    });

    jQuery.validator.addMethod("mustbetrue", function (value, element, params) {

        if ($(element).is(':checked')) {
            return true;
        }
        else {
            return false;
        }
    });
    /*
    START CHECK MAX INT - UNOBTRUSIVE JAVASCRIPT
    START CHECK MAX INT - UNOBTRUSIVE JAVASCRIPT
    START CHECK MAX INT - UNOBTRUSIVE JAVASCRIPT
    */



} (jQuery));

使这项工作有效的原因是……嗯。在尝试执行上述建议的答案后查看 HTML 标记后,我的值都设置为 true,但是我选中的复选框为 false。所以,我决定让 jQuery 使用 IsChecked 来解决它

【讨论】:

  • >> 我不确定为什么这对我不起作用 我也不是 :D 但是您的解决方案是完整和完美的。真的谢谢你。好点子。 +1 干杯。
【解决方案4】:

对于这些解决方案都不起作用的人:

我正在使用 .Net Framework 4 和最新的 jquery 验证脚本文件来处理 Razor MVC 4。

在客户端和服务器端实现自定义属性验证后,它仍然不起作用。无论如何,我的表单正在发布。

所以这里有一个问题: JQuery 验证脚本具有忽略隐藏标签的默认设置,其中隐藏为 http://api.jquery.com/hidden-selector/,这通常不会成为问题,但我正在使用的 @Html.CheckBoxFor 样式是使用 CSS3 样式自定义的,该样式将显示更改为无并显示复选框的自定义图像,因此它永远不会对复选框执行验证规则。

我的解决方法是在自定义客户端验证规则声明之前添加此行:

$.validator.defaults.ignore = "";

它所做的是覆盖当前页面中所有验证的忽略设置,注意现在它也可以在隐藏字段上执行验证(副作用)。

【讨论】:

  • 这让我很生气,直到我想起前端使用了一堆自定义 UI 元素,隐藏了我的输入。 hacky 的解决方案是将输入放置在屏幕外而不是隐藏它。
【解决方案5】:
<script>
    $(function () {
        $('#btnconfirm').click(function () {
            if ($("#chk").attr('checked') !== undefined ){
                return true;
            }
            else {

                alert("Please Select Checkbox ");
                return false;
            }
        });

    });
</script>
<div style="float: left">
                    <input type="checkbox" name="chk" id="chk"  />
                    I read and accept the terms and Conditions of registration
                </div>
  <input type="submit" value="Confirm"  id="btnconfirm" />

【讨论】:

    【解决方案6】:
    /// <summary> 
    ///  Summary : -CheckBox for or input type check required validation is not working the root cause and solution as follows
    ///
    ///  Problem :
    ///  The key to this problem lies in interpretation of jQuery validation 'required' rule. I digged a little and find a specific code inside a jquery.validate.unobtrusive.js file:
    ///  adapters.add("required", function (options) {
    ///  if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
    ///    setValidationValues(options, "required", true);
    ///    }
    ///   });
    ///   
    ///  Fix: (Jquery script fix at page level added in to check box required area)
    ///  jQuery.validator.unobtrusive.adapters.add("brequired", function (options) {
    ///   if (options.element.tagName.toUpperCase() == "INPUT" && options.element.type.toUpperCase() == "CHECKBOX") {
    ///              options.rules["required"] = true;
    ///   if (options.message) {
    ///                   options.messages["required"] = options.message;
    ///                       }
    ///  Fix : (C# Code for MVC validation)
    ///  You can see it inherits from common RequiredAttribute. Moreover it implements IClientValidateable. This is to make assure that rule will be propagated to client side (jQuery validation) as well.
    ///  
    ///  Annotation example :
    ///   [BooleanRequired]
    ///   public bool iAgree { get; set' }
    ///    
    
    /// </summary>
    
    
    public class BooleanRequired : RequiredAttribute, IClientValidatable
    {
    
        public BooleanRequired()
        {
        }
    
        public override bool IsValid(object value)
        {
            return value != null && (bool)value == true;
        }
    
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            return new ModelClientValidationRule[] { new ModelClientValidationRule() { ValidationType = "brequired", ErrorMessage = this.ErrorMessage } };
        }
    }
    

    【讨论】:

    猜你喜欢
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多