jQuery验证:将错误或验证类添加到父div

7

我正在使用Twitter的Bootstrap框架来完成我的一个项目。我尝试使用jQuery Validate插件验证一个简单的联系表格,但是它导致了一些问题。

我想要将错误有效类添加到每个表格输入的父元素div中。这是我的表格代码:

 <form id="msg-form" class="">
    <fieldset>
        <div class="input-prepend control-group pull-left">
            <span class="add-on">@</span>
            <input class="span3 required email" id="inputEmail" name="msg-email" type="text" placeholder="example@example.com">
        </div>
        <div class="input-prepend control-group pull-left">
            <span class="add-on"><i class="icon-user"></i></span>
            <input class="span3 required" id="inputName" name="msg-name" type="text" placeholder="Joe Bloggs">
        </div>
        <div class="input-prepend control-group">
            <span class="add-on" style="height: 53px;"><i class="icon-pencil"></i></span>
            <textarea class="span3 required" id="textarea" name="msg-comments" rows="2" style="height: 53px" placeholder="Just say hi, or tell us how we can help"></textarea>
        </div>
        <button type="submit" class="btn pull-right">Submit<i class="icon-chevron-right"></i></button>
    </fieldset>
</form> 

如您所见,我的
是我想要添加类的div。我尝试使用highlight(如此处建议的),但它根本不起作用,并且使用errorPlacement(见下文)也不正确。
理想情况下,我希望在键盘按键时添加/删除类,以保持插件提供的出色功能。这段简单的代码可以工作,但它不会删除类,而且只能在提交表单时工作:
$("#msg-form").validate({
    errorPlacement: function(error, element) {
        $(element).parent('div').addClass('error');
    }
});

有人能建议我用哪个选项来实现这个吗?!

谢谢提前 - 如有必要,我可以提供任何额外的细节!


看起来应该是 $(error).parent('div').addClass('error');,如果成功了请告诉我。 - gdoron
@gdoron 感谢您的建议,但遗憾的是它并没有起作用。我上面发布的代码会导致类被应用,但存在两个错误: 1.)当字段有效时,它不会移除该类。 2.)它仅适用于错误情况(理想情况下,我希望为有效输入添加另一个类)。 - Sheixt
3个回答

13

尝试使用highlightunhighlight函数:

$("#msg-form").validate({
    highlight: function(element) {
        $(element).parent('div').addClass('error');
    },
    unhighlight: function(element) {
        $(element).parent('div').removeClass('error');
    }
});

谢谢您的建议。事实上,我已经尝试过这种方法了。我按照建议插入了代码,但是没有任何功能...表单验证甚至似乎都没有触发!我已经仔细检查了Firebug,没有出现任何错误。如果有帮助的话,我正在使用插件v1.9.0和jQuery v1.7.1。 - Sheixt
我认为你的<button type="submit">可能需要改为<input type="submit">才能触发验证?不确定表单的提交事件是否可以由<button>触发? - James Simm
没想到会出现这种情况!唉,还是没有成功!!元素类型似乎并没有什么区别。说起来,如果那是问题的原因,连基本验证都不会触发,不是吗?!总之...这很奇怪。我想不出任何(明显的)原因为什么这不起作用。 - Sheixt
你用的是IE浏览器吗?我曾经遇到过验证器将占位符作为值捕获,因此未触发“必填”验证器。 - James Simm
不,我使用Firefox作为主要浏览器来构建项目。之后我将进行跨浏览器测试... 我已经尝试了删除占位符引用,但这仍然无法提交(使用高亮度方法)。 - Sheixt
显示剩余3条评论

4

以下是我对使用jquery validation验证发生错误时添加类到父div的回答,因为我认为这会为此问题提供有价值的解答...

访问验证器设置

首要任务是修改表单验证器上的settings对象。以下是几种可行的方法:

  1. 在所有表单加载之前通过调用jQuery.validator.setDefaults()来设置全局默认值
  2. 在初始化表单时通过在.validate([options])上传递选项来修改
  3. 在初始化之后通过定位带有$("form").data("validator").settings的表单上的验证器对象来进行修改

由于你正在使用MVC,选项#2不可行,因为不唐突验证将自动初始化表单。因此,我们继续使用选项3-这里的目标只是能够自定义表单上的设置。

覆盖默认行为

我们想要修改的默认方法是highlightunhighlight,它们将分别高亮无效字段或恢复由高亮选项所做出的更改。以下是它们的默认行为根据源代码

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函数的包装,这里有几个例子(可以在这里这里这里找到)。以下是从其中一个解析内容简化出来的示例,它可以帮助绑定函数调用中的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>


0
我可能错了,但看起来你需要使用.parents('div.control-group')而不是.parent(),这会将.error添加到错误的div上,而不是将BootStrap表单颜色更改为红色。
这是因为JQuery Validate尝试突出显示的输入在.control-group下方两个位置,而BootStrap要求.error才能生效。
$("#form").validate({
    highlight: function(element, errorClass, validClass){
    $(element).parents("div.control-group").addClass(errorClass).removeClass(validClass);
},

希望这能有所帮助


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