手动向jQuery验证器添加和删除验证错误

时间:2022-08-24 22:16:53

I have a search form & knockout-based grid for results. When search is performed, there is some server-side validation taking place on asp.net mvc, and if model state is not valid, it is returning list of model errors via JSON.

我有一个搜索表单和基于knockout的网格搜索结果。在执行搜索时,在asp.net mvc上进行一些服务器端验证,如果模型状态无效,则通过JSON返回模型错误列表。

I have jQuery validation already set up, and default validations (regex, required etc) are automatically mapped using jquery.unobtrusive plugin. I found $.validate().showErrors({prop:error}) as a way to dynamically show errors based on json response from server, but I'm thinking that this is not proper way to use it for displaying server validation messages, as field cannot be reset afterwards (input-validation-error class is not removed).

我已经设置了jQuery验证,使用jQuery自动映射默认验证(regex, required等)。不引人注目的插件。我发现$.validate(). showerrors ({prop:error})是一种基于服务器json响应动态显示错误的方法,但是我认为这不是用于显示服务器验证消息的正确方法,因为字段之后不能重置(input-validation-error类没有被删除)。

I need a working method for setting & resetting errors on client, if such exists in $.validate.

如果在$.validate中存在错误,我需要一个在客户端设置和重置错误的工作方法。

There is example with my problem on jsFiddle: http://jsfiddle.net/goranobradovic/ughCm/

我在jsFiddle遇到的问题有一个例子:http://jsfiddle.net/goranobradovic/ughCm/

To reproduce it, click add error, then remove error, input stays red.

要复制它,单击添加错误,然后删除错误,输入保持红色。

This is because showErrors function does not add any rules which are triggered by validation, so field stays 'valid' and it is not in elements() list which is used in resetForm to remove input-validation-error class from invalid fields.

这是因为showErrors函数不添加任何由验证触发的规则,所以字段保持“有效”,并且不在resetForm中用于从无效字段中删除输入验证错误类的元素()列表中。

Basically, I want simple way to add/remove validation rule with custom message which is never satisfied on client, to avoid form submission when I set error manually and having to remove invalid class after removing error message.

基本上,我想要一种简单的方法来添加/删除带有自定义消息的验证规则,这在客户端上是永远不会被满足的。

3 个解决方案

#1


18  

I have solved this by overriding showErrors function in jQuery validator with my own, which is compatible with unobtrusive-generated validation spans, and cleaning up valid fields which have invalid class. It is not very nice workaround but it works.

我通过用我自己的jQuery validator重写showErrors函数来解决这个问题,它与不引人注目的生成的验证跨度兼容,并清理具有无效类的有效字段。这不是很好的解决方法,但是很有效。

Here is jsfiddle with solution: http://jsfiddle.net/goranobradovic/ughCm/5/

下面是jsfiddle解决方案:http://jsfiddle.net/goranobradovic/ughCm/5/

UPDATE: As link to external site is not proper answer according to site guidelines, I'm adding code sample here. For anyone already familiar with jQuery validation, just look at two lines of code in showErrors function. I assigned it to validator with validator.settings.showErrors = showErrors;.

更新:由于链接到外部站点不是根据站点指南正确的答案,我在这里添加代码示例。对于熟悉jQuery验证的人,只需查看showErrors函数中的两行代码。我用validator.settings把它分配给validator。showErrors = showErrors;。

HTML:

HTML:

<form id="experiment" action="/" method="post">

<fieldset>
  <legend></legend>
        <div class="editor-label">
          <label for="Email">Email</label>
        </div>
        <div class="editor-field">
<input data-val="true" data-val-email="&amp;#39;Email&amp;#39; not valid email address." data-val-required="&amp;#39;Email&amp;#39; is mandatory." id="Email" name="Email" type="text" value=""><span class="field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true"></span>        
        </div>
        <div class="editor-label">
          <label for="FirstName">First name</label>
        </div>
        <div class="editor-field">
          <input class="text-box single-line" id="FirstName" name="FirstName" type="text" value="">
          <span class="field-validation-valid" data-valmsg-for="FirstName" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
          <label for="LastName">Last name</label>
        </div>
        <div class="editor-field">
          <input class="text-box single-line" id="LastName" name="LastName" type="text" value="">
          <span class="field-validation-valid" data-valmsg-for="LastName" data-valmsg-replace="true"></span>
        </div>   
</fieldset>
    <p>
        <button type="submit" class="save ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-secondary" value="Save" role="button" aria-disabled="false"><span class="ui-button-text">Save</span><span class="ui-button-icon-secondary ui-icon ui-icon-disk"></span></button>

    </p>
</form>
<br/>

<button id="add">Add error</button>
<button id="remove">Remove error</button>

<br/>
<br/>
Debug:
<div id="debug"></div>

JavaScript:

JavaScript:

var validator = {};

function addError(e) {
    validator.showErrors({
        "FirstName": "test error"
    });
}

function removeError(e) {
    validator.showErrors({
        "FirstName": null
    });
    fixValidFieldStyles($("form"), validator);
}

$(document).ready(function() {
    var $form = $("#experiment");
    // prevent form submission
    $form.submit(function(e) {
        e.preventDefault();
        return false;
    });
    $("#add").click(addError);
    $("#remove").click(removeError);
    $("#debug").html("<h1>Validator properties:</h1>");
    validator = $form.validate();
    validator.settings.showErrors = showErrors;
    for (var i in validator) {
        var row = $("<span></span>").html(i).append("<br/>");
        $("#debug").append(row);
    }
});


function showErrors(errorMessage, errormap, errorlist) {
    var val = this;
    errormap.forEach(function(error, index) {
        val.settings.highlight.call(val, error.element, val.settings.errorClass, val.settings.validClass);
        $(error.element).siblings("span.field-validation-valid, span.field-validation-error").html($("<span></span>").html(error.message)).addClass("field-validation-error").removeClass("field-validation-valid").show();
    });
}

function fixValidFieldStyles($form, validator) {
    var errors = {};
    $form.find("input,select").each(function(index) {
        var name = $(this).attr("name");
        errors[name] = validator.errorsFor(name);
    });
    validator.showErrors(errors);
    var invalidFields = $form.find("." + validator.settings.errorClass);
    if (invalidFields.length) {
        invalidFields.each(function(index, field) {
            if ($(field).valid()) {
                $(field).removeClass(validator.settings.errorClass);
            }
        });
    }
}

#2


8  

I did something a bit simpler - basically added the ability to more fully register the error into the validator. I added the following to jquery.validate.js (underneath showErrors):

我做了一些更简单的事情——基本上增加了在验证器中更完整地注册错误的能力。我添加了下面的jquery.validate。js(下面showErrors):

addErrors: function (errors) {
        for (var i = 0; i < errors.length; i++) {
            this.errorList.push({
                element: $(errors[i].element)[0],
                message: errors[i].message
            });
        }           
        this.showErrors();
    },

then instead of calling form.validate().showErrors() you can do e.g.

然后不用调用form.validate(). showerrors(),你可以这样做。

form.validate().addErrors([{
    element: $('#myinput'),
    message: 'A manual error message'
}]);

Finally because the form may not have been marked as invalid when submitted, you may want to force a validation on keyup or similar:

最后,由于表单在提交时可能没有被标记为无效,所以您可能需要强制对keyup或类似的验证:

$('#myinput').one('keyup', function(){ $(this).valid(); });

(Note: this isn't battle-tested but I'm sure at the very least a solution lies down this way somewhere)

(注意:这不是经过实战检验的,但我肯定至少有一个解决方案就在这个地方)

#3


4  

I ended up solving the problem in a simple way cleaning the errors and then showing the new errors.

我以一种简单的方式解决了这个问题,清除了错误,然后显示了新的错误。

// get the form inside we are working - change selector to your form as needed
var $form = $("form");

// get validator object
var $validator = $form.validate();

// get errors that were created using jQuery.validate.unobtrusive
var $errors = $form.find(".field-validation-error span");

// trick unobtrusive to think the elements were succesfully validated
// this removes the validation messages
$errors.each(function(){ $validator.settings.success($(this)); })

// clear errors from validation
$validator.resetForm();

// Then show the errors
$.validator().showErrors({prop:error}

#1


18  

I have solved this by overriding showErrors function in jQuery validator with my own, which is compatible with unobtrusive-generated validation spans, and cleaning up valid fields which have invalid class. It is not very nice workaround but it works.

我通过用我自己的jQuery validator重写showErrors函数来解决这个问题,它与不引人注目的生成的验证跨度兼容,并清理具有无效类的有效字段。这不是很好的解决方法,但是很有效。

Here is jsfiddle with solution: http://jsfiddle.net/goranobradovic/ughCm/5/

下面是jsfiddle解决方案:http://jsfiddle.net/goranobradovic/ughCm/5/

UPDATE: As link to external site is not proper answer according to site guidelines, I'm adding code sample here. For anyone already familiar with jQuery validation, just look at two lines of code in showErrors function. I assigned it to validator with validator.settings.showErrors = showErrors;.

更新:由于链接到外部站点不是根据站点指南正确的答案,我在这里添加代码示例。对于熟悉jQuery验证的人,只需查看showErrors函数中的两行代码。我用validator.settings把它分配给validator。showErrors = showErrors;。

HTML:

HTML:

<form id="experiment" action="/" method="post">

<fieldset>
  <legend></legend>
        <div class="editor-label">
          <label for="Email">Email</label>
        </div>
        <div class="editor-field">
<input data-val="true" data-val-email="&amp;#39;Email&amp;#39; not valid email address." data-val-required="&amp;#39;Email&amp;#39; is mandatory." id="Email" name="Email" type="text" value=""><span class="field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true"></span>        
        </div>
        <div class="editor-label">
          <label for="FirstName">First name</label>
        </div>
        <div class="editor-field">
          <input class="text-box single-line" id="FirstName" name="FirstName" type="text" value="">
          <span class="field-validation-valid" data-valmsg-for="FirstName" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
          <label for="LastName">Last name</label>
        </div>
        <div class="editor-field">
          <input class="text-box single-line" id="LastName" name="LastName" type="text" value="">
          <span class="field-validation-valid" data-valmsg-for="LastName" data-valmsg-replace="true"></span>
        </div>   
</fieldset>
    <p>
        <button type="submit" class="save ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-secondary" value="Save" role="button" aria-disabled="false"><span class="ui-button-text">Save</span><span class="ui-button-icon-secondary ui-icon ui-icon-disk"></span></button>

    </p>
</form>
<br/>

<button id="add">Add error</button>
<button id="remove">Remove error</button>

<br/>
<br/>
Debug:
<div id="debug"></div>

JavaScript:

JavaScript:

var validator = {};

function addError(e) {
    validator.showErrors({
        "FirstName": "test error"
    });
}

function removeError(e) {
    validator.showErrors({
        "FirstName": null
    });
    fixValidFieldStyles($("form"), validator);
}

$(document).ready(function() {
    var $form = $("#experiment");
    // prevent form submission
    $form.submit(function(e) {
        e.preventDefault();
        return false;
    });
    $("#add").click(addError);
    $("#remove").click(removeError);
    $("#debug").html("<h1>Validator properties:</h1>");
    validator = $form.validate();
    validator.settings.showErrors = showErrors;
    for (var i in validator) {
        var row = $("<span></span>").html(i).append("<br/>");
        $("#debug").append(row);
    }
});


function showErrors(errorMessage, errormap, errorlist) {
    var val = this;
    errormap.forEach(function(error, index) {
        val.settings.highlight.call(val, error.element, val.settings.errorClass, val.settings.validClass);
        $(error.element).siblings("span.field-validation-valid, span.field-validation-error").html($("<span></span>").html(error.message)).addClass("field-validation-error").removeClass("field-validation-valid").show();
    });
}

function fixValidFieldStyles($form, validator) {
    var errors = {};
    $form.find("input,select").each(function(index) {
        var name = $(this).attr("name");
        errors[name] = validator.errorsFor(name);
    });
    validator.showErrors(errors);
    var invalidFields = $form.find("." + validator.settings.errorClass);
    if (invalidFields.length) {
        invalidFields.each(function(index, field) {
            if ($(field).valid()) {
                $(field).removeClass(validator.settings.errorClass);
            }
        });
    }
}

#2


8  

I did something a bit simpler - basically added the ability to more fully register the error into the validator. I added the following to jquery.validate.js (underneath showErrors):

我做了一些更简单的事情——基本上增加了在验证器中更完整地注册错误的能力。我添加了下面的jquery.validate。js(下面showErrors):

addErrors: function (errors) {
        for (var i = 0; i < errors.length; i++) {
            this.errorList.push({
                element: $(errors[i].element)[0],
                message: errors[i].message
            });
        }           
        this.showErrors();
    },

then instead of calling form.validate().showErrors() you can do e.g.

然后不用调用form.validate(). showerrors(),你可以这样做。

form.validate().addErrors([{
    element: $('#myinput'),
    message: 'A manual error message'
}]);

Finally because the form may not have been marked as invalid when submitted, you may want to force a validation on keyup or similar:

最后,由于表单在提交时可能没有被标记为无效,所以您可能需要强制对keyup或类似的验证:

$('#myinput').one('keyup', function(){ $(this).valid(); });

(Note: this isn't battle-tested but I'm sure at the very least a solution lies down this way somewhere)

(注意:这不是经过实战检验的,但我肯定至少有一个解决方案就在这个地方)

#3


4  

I ended up solving the problem in a simple way cleaning the errors and then showing the new errors.

我以一种简单的方式解决了这个问题,清除了错误,然后显示了新的错误。

// get the form inside we are working - change selector to your form as needed
var $form = $("form");

// get validator object
var $validator = $form.validate();

// get errors that were created using jQuery.validate.unobtrusive
var $errors = $form.find(".field-validation-error span");

// trick unobtrusive to think the elements were succesfully validated
// this removes the validation messages
$errors.each(function(){ $validator.settings.success($(this)); })

// clear errors from validation
$validator.resetForm();

// Then show the errors
$.validator().showErrors({prop:error}