jquery.validate.unobtrusive 不适用于动态注入元素

发布于 2024-10-07 03:09:06 字数 254 浏览 6 评论 0原文

我正在使用 ASP.Net MVC3,使用客户端验证的更简单方法是启用 jquery.validate.unobtrusive。一切正常,对于来自服务器的东西。

但是当我尝试用 javascript 注入一些新的“输入”时,我知道我需要调用 $.validator.unobtrusive.parse() 来重新绑定验证。但是,所有这些动态注入场仍然无法发挥作用。

更糟糕的是,我尝试使用 jquery.validate 手动绑定,但它也不起作用。有什么想法吗?

I am working with ASP.Net MVC3, the easier way to use the client validation would be enabling the jquery.validate.unobtrusive. Everything works fine, for stuff that's right from server.

But when I try to inject some new 'inputs' with javascript, and I knew that I need to call $.validator.unobtrusive.parse() to rebind the validations. But still, all those dynamic injected fields are not functioning.

Even worse, I try to manually bind using jquery.validate and it is not working either. Any thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

静谧幽蓝 2024-10-14 03:09:06

我尝试了 Xhalent 的方法,但不幸的是它对我不起作用。罗宾的方法有效,也无效。它对于动态添加的元素非常有效,但如果您尝试使用 JQuery 从 DOM 中删除所有验证属性和跨度,验证库仍然会尝试验证它们。

但是,如果您除了“validationData”之外还删除了表单的“unobtrusiveValidation”数据,那么它就像一个魅力,可以动态添加和删除您想要验证或不验证的元素。

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");

I tried Xhalent's approach but unfortunately it wasn't working for me. Robin's approach did work and didn't work. It worked great for dynamically added elements, but if you tried to use JQuery to remove all the validation attributes and spans from the DOM, the validation library still would try to validate them.

However, if you remove the form's "unobtrusiveValidation" data in addition to "validationData", it worked like a charm for dynamically adding and removing elements that you want validated or not validated.

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
画骨成沙 2024-10-14 03:09:06

我已经为 jquery.validate.unobtrusive 库创建了一个扩展,它针对我的情况解决了这个问题 - 它可能很有趣。

http://xhalent.wordpress.com/2011/01/24 /将不引人注目的验证应用于动态内容/

I've created an extension for the jquery.validate.unobtrusive library that solved this problem for my situation - it might be of interest.

http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/

鲜肉鲜肉永远不皱 2024-10-14 03:09:06

我实际上真的很喜欢@viggity和@Robins解决方案的简单性,所以我把它变成了一个快速的小插件:

(function ($) {

    $.fn.updateValidation = function () {
        var $this = $(this);
        var form = $this.closest("form")
            .removeData("validator")
            .removeData("unobtrusiveValidation");

        $.validator.unobtrusive.parse(form);

        return $this;
    };
})(jQuery);

示例用法:

$("#DischargeOutcomeNumberOfVisits")
    .attr("data-val-range-min", this.checked ? "1" : "2")
    .updateValidation();

I actually really like the simplicity of @viggity and @Robins solution, so I turned it into a quick little plugin:

(function ($) {

    $.fn.updateValidation = function () {
        var $this = $(this);
        var form = $this.closest("form")
            .removeData("validator")
            .removeData("unobtrusiveValidation");

        $.validator.unobtrusive.parse(form);

        return $this;
    };
})(jQuery);

Example usage:

$("#DischargeOutcomeNumberOfVisits")
    .attr("data-val-range-min", this.checked ? "1" : "2")
    .updateValidation();
维持三分热 2024-10-14 03:09:06

我也有同样的问题。我发现不可能在同一个表单上调用 $.validator.unobtrusive.parse() 两次。
当最初从服务器加载表单时,不显眼的库会自动解析表单。当您动态地将输入元素添加到表单并再次调用 $.validator.unobtrusive.parse() 时,它将不起作用。 parseElement() 也是如此。

unobtrusive lib 调用 jquery validate 插件的 validate 方法来设置所有规则和消息。问题是,当再次调用时,插件不会更新其给定的新规则集。

我找到了一个粗略的解决方案:在调用不显眼的库上的解析方法之前,我扔掉了表单验证器:

$('yourForm').removeData("validator");

现在,当不显眼的库调用验证方法时,将重新创建所有规则和消息,包括动态添加的输入。

希望这有帮助

I'm having the same problem. I discovered it's not possible to call $.validator.unobtrusive.parse() on the same form twice.
When loading the form initially from the server the form is parsed automatically by the unobtrusive library. When you add an input element dynamically to the form and call $.validator.unobtrusive.parse() again, it won't work. The same goes for parseElement().

The unobtrusive lib calls the validate method of the jquery validate plugin to set all the rules and messages. Problem is, when called again, the plugin doesn't update the new set of rules its given.

I found one crude solution: Before calling the parse method on the unobstrusive lib, i throw away the form validator:

$('yourForm').removeData("validator");

Now, when the validate method is called by the unobtrusive lib, all rules and messages are recreated including the dynamically added inputs.

Hope this helps

年少掌心 2024-10-14 03:09:06

我正在使用 MVC 4 和 JQuery 1.8, 看起来需要以下代码来使 Jquery 能够验证通过 Ajax 或 Jquery 动态注入到 DOM 的内容。

我制作了一个模块化函数,它接受新添加元素的 Jquery 对象。
如果您通过单击按钮使用 Jquery 克隆了 id 为 tblContacts 的新表,则将以下函数包含在您的 js 文件中

function fnValidateDynamicContent(element) {
    var currForm = element.closest("form");
    currForm.removeData("validator");
    currForm.removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse(currForm);
    currForm.validate(); // This line is important and added for client side validation to trigger, without this it didn't fire client side errors.
}

并按如下方式调用:

fnValidateDynamicContent("#tblContacts")

I am using MVC 4 and JQuery 1.8, looks like the following piece of code is needed to enable Jquery to validation dynamically injected content via Ajax, or Jquery into the DOM.

I have made a modular function which accepts the Jquery object of the newly added element.
If you have cloned a new table with id tblContacts using Jquery on click of a button, then include the function below in your js file

function fnValidateDynamicContent(element) {
    var currForm = element.closest("form");
    currForm.removeData("validator");
    currForm.removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse(currForm);
    currForm.validate(); // This line is important and added for client side validation to trigger, without this it didn't fire client side errors.
}

and call it like this:

fnValidateDynamicContent("#tblContacts")
冰火雁神 2024-10-14 03:09:06

我尝试了 vivigity 的答案,起初一切似乎都有效。但过了一段时间,我注意到我添加的动态项目越多,验证速度就越慢。原因是他的解决方案不会解除事件处理程序的绑定,而是每次都添加新的事件处理程序。因此,如果添加 5 个项目,验证将执行 6 次,而不是仅执行一次。要解决此问题,您必须将事件与removeData 调用一起解除绑定。

$("form").removeData("validator")
         .removeData("unobtrusiveValidation")
         .off("submit.validate click.validate focusin.validate focusout.validate keyup.validate invalid-form.validate");
$.validator.unobtrusive.parse("form");

I tried viggity's answer and at first everything seemed to work. But after a while i noticed that the validation becomes painfully slow the more dynamically items I added. The reason was that his solution doesn't unbind the event handlers, but add new ones each time. So if you add 5 items the validation is executed 6 times instead of only once. To fix this you have to unbind the events additionally to the removeData calls.

$("form").removeData("validator")
         .removeData("unobtrusiveValidation")
         .off("submit.validate click.validate focusin.validate focusout.validate keyup.validate invalid-form.validate");
$.validator.unobtrusive.parse("form");
飘落散花 2024-10-14 03:09:06

为什么不直接使用 jquery 验证文档中的规则函数。像这样:

$('#newField0').rules('add', {
    required: true,
    minlength: 2
});
//use Html.ValidationMessage will renders a span element, unobtrusive need it to display errors
$('@Html.ValidationMessage("newField0")').insertAfter('#newField0');

Why not use the rules function directly from jquery validation doc. Like this:

$('#newField0').rules('add', {
    required: true,
    minlength: 2
});
//use Html.ValidationMessage will renders a span element, unobtrusive need it to display errors
$('@Html.ValidationMessage("newField0")').insertAfter('#newField0');
剪不断理还乱 2024-10-14 03:09:06

借鉴上面标记为答案的 Xhalent 解决方案,我对其进行了一些扩展。

$.validator.unobtrusive.parseDynamicContent = function (selector) {
    var $selector = $(selector),
        $jqValUnob = $.validator.unobtrusive,
        selectorsDataValAttr = $selector.attr('data-val'),
        $validationInputs = $selector.find(':input[data-val=true]');

    if ((selectorsDataValAttr !== 'true') && 
        ($validationInputs.length === 0)) { 
        return; 
    }

    if (selectorsDataValAttr === 'true') {
        $jqValUnob.parseElement(selector, true);
    }

    $validationInputs.each(function () {
        $jqValUnob.parseElement(this, true);
    });

    //get the relevant form
    var $form = $selector.first().closest('form');

    $jqValUnob.syncValdators($form);
};

/* synchronizes the unobtrusive validation with jquery validator */
$.validator.unobtrusive.syncValdators = function ($form) {
    if ($.hasData($form[0])) {
        var unobtrusiveValidation = $form.data('unobtrusiveValidation'),
            validator = $form.validate();

        // add validation rules from unobtrusive to jquery
        $.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
            if (validator.settings.rules[elname] == undefined) {
                var args = {};
                $.extend(args, elrules);
                args.messages = unobtrusiveValidation.options.messages[elname];
                $("[name='" + elname + "']").rules("add", args);
            } else {
                $.each(elrules, function (rulename, data) {
                    if (validator.settings.rules[elname][rulename] == undefined) {
                        var args = {};
                        args[rulename] = data;
                        args.messages = unobtrusiveValidation.options.messages[elname][rulename];
                        $("[name='" + elname + "']").rules("add", args);
                    }
                });
            }
        });
        // remove all validation rules from jquery that arn't in unobtrusive
        $.each(validator.settings.rules, function (elname, elrules) {
            if (unobtrusiveValidation.options.rules[elname] === undefined) {
                delete validator.settings.rules[elname];
            } else {
                $.each(elrules, function (rulename, data) {
                    if (rulename !== "messages" && unobtrusiveValidation.options.rules[elname][rulename] === undefined) {
                        delete validator.settings.rules[elname][rulename];
                    }
                });
            }
        });
    }        
};

$.validator.unobtrusive.unparseContent = function (selector) {
    var $selector = $(selector);

    // if its  a text node, then exit
    if ($selector && $selector.length > 0 && $selector[0].nodeType === 3) {
        return;
    }

    var $form = $selector.first().closest('form'), 
        unobtrusiveValidation = $form.data('unobtrusiveValidation');

    $selector.find(":input[data-val=true]").each(function () {
        removeValidation($(this), unobtrusiveValidation);
    });
    if ($selector.attr('data-val') === 'true') {
        removeValidation($selector, unobtrusiveValidation);
    }
    $.validator.unobtrusive.syncValdators($form);
};

function removeValidation($element, unobtrusiveValidation) {
    var elname = $element.attr('name');
    if (elname !== undefined) {
        $element.rules('remove');
        if (unobtrusiveValidation) {
            if (unobtrusiveValidation.options.rules[elname]) {
                delete unobtrusiveValidation.options.rules[elname];
            }
            if (unobtrusiveValidation.options.messages[elname]) {
                delete unobtrusiveValidation.options.messages[elname];
            }
        }
    }
}

所以基本上它仍然与上面的 Xhalent 解决方案相同,但我添加了删除从 dom 中删除的元素的规则的功能。因此,当您从 Dom 中删除元素并且希望删除这些验证规则时,请调用:

$.validator.unobtrusive.unparseContent('input.something');

Taking from Xhalent's solution marked as answer above, I expanded on it a bit.

$.validator.unobtrusive.parseDynamicContent = function (selector) {
    var $selector = $(selector),
        $jqValUnob = $.validator.unobtrusive,
        selectorsDataValAttr = $selector.attr('data-val'),
        $validationInputs = $selector.find(':input[data-val=true]');

    if ((selectorsDataValAttr !== 'true') && 
        ($validationInputs.length === 0)) { 
        return; 
    }

    if (selectorsDataValAttr === 'true') {
        $jqValUnob.parseElement(selector, true);
    }

    $validationInputs.each(function () {
        $jqValUnob.parseElement(this, true);
    });

    //get the relevant form
    var $form = $selector.first().closest('form');

    $jqValUnob.syncValdators($form);
};

/* synchronizes the unobtrusive validation with jquery validator */
$.validator.unobtrusive.syncValdators = function ($form) {
    if ($.hasData($form[0])) {
        var unobtrusiveValidation = $form.data('unobtrusiveValidation'),
            validator = $form.validate();

        // add validation rules from unobtrusive to jquery
        $.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
            if (validator.settings.rules[elname] == undefined) {
                var args = {};
                $.extend(args, elrules);
                args.messages = unobtrusiveValidation.options.messages[elname];
                $("[name='" + elname + "']").rules("add", args);
            } else {
                $.each(elrules, function (rulename, data) {
                    if (validator.settings.rules[elname][rulename] == undefined) {
                        var args = {};
                        args[rulename] = data;
                        args.messages = unobtrusiveValidation.options.messages[elname][rulename];
                        $("[name='" + elname + "']").rules("add", args);
                    }
                });
            }
        });
        // remove all validation rules from jquery that arn't in unobtrusive
        $.each(validator.settings.rules, function (elname, elrules) {
            if (unobtrusiveValidation.options.rules[elname] === undefined) {
                delete validator.settings.rules[elname];
            } else {
                $.each(elrules, function (rulename, data) {
                    if (rulename !== "messages" && unobtrusiveValidation.options.rules[elname][rulename] === undefined) {
                        delete validator.settings.rules[elname][rulename];
                    }
                });
            }
        });
    }        
};

$.validator.unobtrusive.unparseContent = function (selector) {
    var $selector = $(selector);

    // if its  a text node, then exit
    if ($selector && $selector.length > 0 && $selector[0].nodeType === 3) {
        return;
    }

    var $form = $selector.first().closest('form'), 
        unobtrusiveValidation = $form.data('unobtrusiveValidation');

    $selector.find(":input[data-val=true]").each(function () {
        removeValidation($(this), unobtrusiveValidation);
    });
    if ($selector.attr('data-val') === 'true') {
        removeValidation($selector, unobtrusiveValidation);
    }
    $.validator.unobtrusive.syncValdators($form);
};

function removeValidation($element, unobtrusiveValidation) {
    var elname = $element.attr('name');
    if (elname !== undefined) {
        $element.rules('remove');
        if (unobtrusiveValidation) {
            if (unobtrusiveValidation.options.rules[elname]) {
                delete unobtrusiveValidation.options.rules[elname];
            }
            if (unobtrusiveValidation.options.messages[elname]) {
                delete unobtrusiveValidation.options.messages[elname];
            }
        }
    }
}

So basically it still works the same as Xhalent's solution above but I added the ability to remove rules for elements you remove from the dom. So, when you remove elements from the Dom and you want those validation rules removed also then call:

$.validator.unobtrusive.unparseContent('input.something');
一袭白衣梦中忆 2024-10-14 03:09:06

我已经摆弄这个问题有一段时间了,放弃解决方案并稍后再试(当我有空闲时间时,信不信由你)。

我不确定这种行为在较新版本的 jquery(我们使用的是 1.7.2)中是否会发生变化,因为该线程是最后创建或评论的,但我发现 .parseElement(inputElement) 有效当我尝试将动态创建的元素添加到已加载验证器的表单时,效果很好。
@jamesfm(2011 年 2 月 15 日)在上面的评论之一中已经建议了这一点,但我在最初几次从事此工作时忽略了它。因此,我将其添加为单独的答案,以使其更加明显,因为我认为这是一个很好的解决方案,并且不需要太多开销。它可能与后续答案中提出的所有问题无关,但我认为这将是原始问题的解决方案。这是我的工作方式:

//row & textarea created dynamically by an async ajax call further up in the code
var row = ...; //row reference from somewhere
var textarea = row.find("textarea");
textarea.val("[someValue]");

//add max length rule to the text area
textarea.rules('add', {
    maxlength: 2000
});
//parse the element to enable the validation on the dynamically added element
$.validator.unobtrusive.parseElement(textarea);

I have been fiddling around with this for a while, scrapping solutions and trying again later (when I had some spare time, believe it or not).

I am not sure if this behaviour would have changed in newer versions of jquery (we're using 1.7.2) since this thread was created or commented last, but I found that .parseElement(inputElement) works fine when I try to add dynamically created elements to a form that already has a validator loaded.
This was already suggested by @jamesfm (Feb 15 '11) in one of the comments above, but I overlooked it the first few times I was working on this. So I'm adding it as a separate answer to make it more obvious and because I think it is a good solution and doesn't require so much overhead. It might not be relevant for all the issues raised in subsequent answers but I think it would be a solution to the original question. Here's how I got mine working:

//row & textarea created dynamically by an async ajax call further up in the code
var row = ...; //row reference from somewhere
var textarea = row.find("textarea");
textarea.val("[someValue]");

//add max length rule to the text area
textarea.rules('add', {
    maxlength: 2000
});
//parse the element to enable the validation on the dynamically added element
$.validator.unobtrusive.parseElement(textarea);
他夏了夏天 2024-10-14 03:09:06

我在我的代码中找到了 @Xhalent 的代码脚本,并打算将其删除,因为我没有使用它,这导致我提出了这个问题。

这段代码非常干净和简单:

jQuery.fn.unobtrusiveValidationForceBind = function () {
    //If you try to parse a form that is already parsed it won't update
    var $form = this
       .removeData("validator") /* added by the raw jquery.validate plugin */
            .removeData("unobtrusiveValidation");  /* added by the jquery     unobtrusive plugin */

    $form.bindUnobtrusiveValidation();
}

然后,要调用这个 jQuery 扩展,只需使用选择器来抓取表单:

$('#formStart').unobtrusiveValidationForceBind();

Viola!

I found @Xhalent's code script in my code and was going to delete it because I was not using it, which lead me to this SO question.

This code is pretty clean and simple:

jQuery.fn.unobtrusiveValidationForceBind = function () {
    //If you try to parse a form that is already parsed it won't update
    var $form = this
       .removeData("validator") /* added by the raw jquery.validate plugin */
            .removeData("unobtrusiveValidation");  /* added by the jquery     unobtrusive plugin */

    $form.bindUnobtrusiveValidation();
}

Then, to call this jQuery extension, just use a selector to grab you form:

$('#formStart').unobtrusiveValidationForceBind();

Viola!

_畞蕅 2024-10-14 03:09:06

如果是动态内容,您需要更新不显眼的验证,如下所示,并在提交时检查 Form 是否有效。

function UpdateUnobtrusiveValidations(idForm) {
    $(idForm).removeData("validator").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse($(idForm));
};


$('#idDivPage').on('click', '#idSave', function (e) {
    e.preventDefault();
    if (!$('#idForm').valid()) {
        // Form is invalid … so return
        return false;
    }
    else {
        // post data to server using ajax call
        // update Unobtrusive Validations again
        UpdateUnobtrusiveValidations('#idForm');
    }
});

In case of dynamic contents you need to update Unobtrusive Validations as below and check if Form is valid while submitting.

function UpdateUnobtrusiveValidations(idForm) {
    $(idForm).removeData("validator").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse($(idForm));
};


$('#idDivPage').on('click', '#idSave', function (e) {
    e.preventDefault();
    if (!$('#idForm').valid()) {
        // Form is invalid … so return
        return false;
    }
    else {
        // post data to server using ajax call
        // update Unobtrusive Validations again
        UpdateUnobtrusiveValidations('#idForm');
    }
});
荒人说梦 2024-10-14 03:09:06

首先,我认为调用应该是.validator,而不是验证然后你需要传入表单的id

$.validator.unobtrusive.parse("#id");

Firstly, I think the call should be to .validator, not validate then you need to pass in the id of the form

$.validator.unobtrusive.parse("#id");
执手闯天涯 2024-10-14 03:09:06

如果您需要添加和删除可能已经显示一些错误的内容,这就是我所提供的。它主要基于这个问题页面上的不同想法。我使用内置的 destroy() 而不是仅仅删除 JQuery 验证的数据属性。

function resetValidator($form: JQuery) {
    $form.validate().destroy();

    //reset unobtrusive validation summary, if it exists
    $form.find("[data-valmsg-summary=true]")
        .removeClass("validation-summary-errors")
        .addClass("validation-summary-valid")
        .find("ul").empty();

    //reset unobtrusive field level, if it exists
    $form.find("[data-valmsg-replace]")
        .removeClass("field-validation-error")
        .addClass("field-validation-valid")
        .empty();

    $form.removeData("unobtrusiveValidation");
}

您可以在动态修改表单中的输入之前调用它。然后您可以重新初始化验证。

resetValidator($form);
//add or remove inputs here ...
$.validator.unobtrusive.parse($form);

注意:如果某些或所有输入已被验证并且有错误,这些错误将被重置......但它们将在下一次验证时正确返回。

If you need to add and remove things with the possibility that some errors are already displayed, this is what I came with. It is based mainly on different ideas on this question page. I use the built in destroy() instead of just removing the data attribute for JQuery validate.

function resetValidator($form: JQuery) {
    $form.validate().destroy();

    //reset unobtrusive validation summary, if it exists
    $form.find("[data-valmsg-summary=true]")
        .removeClass("validation-summary-errors")
        .addClass("validation-summary-valid")
        .find("ul").empty();

    //reset unobtrusive field level, if it exists
    $form.find("[data-valmsg-replace]")
        .removeClass("field-validation-error")
        .addClass("field-validation-valid")
        .empty();

    $form.removeData("unobtrusiveValidation");
}

You call it before dynamically modifying the inputs in the form. You then reinitialize the validation after.

resetValidator($form);
//add or remove inputs here ...
$.validator.unobtrusive.parse($form);

Note: If some or all inputs have been validated and have errors, those errors will be reset... but they will correctly come back on the next validation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文