【问题标题】:Add class to parent div if validation error occurs using jquery validation如果使用 jquery 验证发生验证错误,则将类添加到父 div
【发布时间】:2011-12-18 15:54:33
【问题描述】:

我的输入字段有以下标记:

<div class="required">
    <label for="Name">Name <em>*</em></label>           
    <div class="input large">
        @Html.TextBoxFor(m => m.Name)
        @Html.ValidationMessageFor(m => m.Name)
    </div>
</div>

如果发生错误,则使用 jquery 验证插件,然后它将在输入下方添加一个跨度,并将一个类应用于输入本身,以便可以为错误设置样式。我还想做的是向父 div 添加一个类,其中包含一个必需的类。因此,例如,如果发生错误,它将是 &lt;div class="required error"&gt;,然后当修复 &lt;div class="required valid"&gt; 时,与应用于该字段的类有关并删除错误范围。

我该怎么做?我查看了文档站点,但没有看到将类添加到父 div 的任何内容。

我想过做类似的事情:

if ($('input').hasClass('valid')) {
    $(this).parents('div.required').addClass('valid');

} else if ($('input').hasClass('input-validation-error')) {
    $(this).parents('div.required').addClass('error');
}

但是我怎样才能通过验证来运行它呢?就像发生错误或字段变为有效时一样。

【问题讨论】:

  • 继续希望。我认为你将不得不重写 jQuery 的验证方法来做你想做的事情。我假设您使用的是不显眼的验证,并且只会突出显示字段本身。
  • 那是正确的,但是某种自定义 jquery 会说什么,比如在输入中有一个类,然后让父 div 有一个类?然后在输入字段的类发生更改时运行此代码。例如,参见 OP。

标签: jquery asp.net-mvc jquery-validate


【解决方案1】:

访问验证器设置

首要任务是修改表单验证器上的settings 对象。您可以通过以下任一方式执行此操作:

  1. 在为所有表单加载表单之前调用jQuery.validator.setDefaults()
  2. 通过传入.validate([options]) 上的选项来初始化表单时
  3. 在初始化后通过在表单上使用$("form").data("validator").settings 定位验证器对象

由于您使用的是 MVC,所以选项 #2 是不可能的,因为 unobtrusive-validation 将自动初始化表单。所以让我们继续使用选项 3 - 这里的目标只是能够自定义表单上的设置。

覆盖默认行为

我们要修改的默认方法是highlightunhighlight,它们将分别高亮无效字段或恢复高亮选项所做的更改。这是他们的默认行为according to the source code

highlight: function( element, errorClass, validClass ) {
    if ( element.type === "radio" ) {
        this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
    } else {
        $( element ).addClass( errorClass ).removeClass( validClass );
    }
},
unhighlight: function( element, errorClass, validClass ) {
    if ( element.type === "radio" ) {
        this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
    } else {
        $( element ).removeClass( errorClass ).addClass( validClass );
    }
}

所以你在这里也有几个选择。

  1. 完全替换那些函数,自己写
  2. 包装这些函数并像往常一样调用它们,但在之前或之后添加您自己的自定义代码。

选项 1 - 替换批发

这条路线很简单。随便在里面写什么就行了。也许从源代码种子,也许做你自己的事情。

var valSettings = $("form").data("validator").settings
valSettings.highlight = function(element, errorClass, validClass) { ... }
valSettings.unhighlight = function(element, errorClass, validClass) { ... }

选项 2 - 包装函数

这不太麻烦,所以在大多数情况下可能更可取。

由于最终您将替换 valSettings.highlight 的值,因此您需要访问原始函数的干净原始版本。您可以保存自己的或从全局默认值中获取一个

// original highlight function
var highlightOriginal = $("form").data("validator").settings.highlight;
var highlightDefaults = $.validator.defaults.highlight

在包装 JavaScript 函数方面,有几个示例 hereherehere)。这是其中之一的解析示例,这将有助于在函数调用之间绑定 this 上下文,保留所传递参数的数量,并保留返回值:

function wrap(functionToWrap, beforeFunction) {
    return function () {
        var args = Array.prototype.slice.call(arguments),
        beforeFunction.apply(this, args);
        return functionToWrap.apply(this, args);
    };
};

然后,您还必须快速定义在调用时要触发的任何其他行为。在这种情况下,让我们找到最接近元素的父 div 并像这样更新它的类:

function highlightDecorator(element, errorClass, validClass) {
    $(element).closest("div").addClass(errorClass).removeClass(validClass);
}

总结一下 (看看我做了什么)

$(function () {
  var valSettings = $("form").data("validator").settings
  valSettings.highlight = wrap($.validator.defaults.highlight, highlightDecorator)
  valSettings.unhighlight = wrap($.validator.defaults.unhighlight, unhighlightDecorator)
});

function wrap(functionToWrap, beforeFunction) {
  return function () {
    var args = Array.prototype.slice.call(arguments);
    beforeFunction.apply(this, args);
    return functionToWrap.apply(this, args);
  };
};

function highlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(errorClass).removeClass(validClass);
}
function unhighlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(validClass).removeClass(errorClass);
}

所以当我们结合以上所有功能时,它应该看起来像这样:

Stack Snippets 和 jsFiddle 中的工作演示

$(function () {
  var valSettings = $("form").data("validator").settings
	valSettings.highlight = wrap($.validator.defaults.highlight, highlightDecorator)
  valSettings.unhighlight = wrap($.validator.defaults.unhighlight, unhighlightDecorator)
});

function wrap(functionToWrap, beforeFunction) {
  return function () {
    var args = Array.prototype.slice.call(arguments);
    beforeFunction.apply(this, args);
    return functionToWrap.apply(this, args);
  };
};

function highlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(errorClass).removeClass(validClass);
}
function unhighlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(validClass).removeClass(errorClass);
}
input.input-validation-error  {
  border: solid 1px red;
}
.input-validation-error label {
  color: red;
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.16.0/jquery.validate.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"></script>
    
<form action="/Person" method="post">
  
  <div class="required">
    <label for="Name">Name <em>*</em></label>           
    <input id="Name" name="Name" type="text" value="" 
           data-val="true" data-val-required="The Name field is required."/>
    <span class="field-validation-valid" 
          data-valmsg-for="Name" data-valmsg-replace="true"></span>
  </div>
  
  <input type="submit" value="Save" />
  
</form>

【讨论】:

    【解决方案2】:

    我根本没有玩过这个,但你也许可以使用jQuery Validate Hooks

    【讨论】:

      猜你喜欢
      • 2012-05-13
      • 1970-01-01
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-07
      • 2015-12-15
      相关资源
      最近更新 更多