jquery.validate.unobtrusive not working with dynam

2018-12-31 19:44发布

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?

12条回答
还给你的自由
2楼-- · 2018-12-31 20:33

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");
查看更多
萌妹纸的霸气范
3楼-- · 2018-12-31 20:36

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');
查看更多
只若初见
4楼-- · 2018-12-31 20:44

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");
查看更多
余欢
5楼-- · 2018-12-31 20:44

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

查看更多
呛了眼睛熬了心
6楼-- · 2018-12-31 20:44

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');
    }
});
查看更多
无色无味的生活
7楼-- · 2018-12-31 20:46

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!

查看更多
登录 后发表回答