jquery.утверждать.ненавязчивая работа с динамическими инжектируемыми элементами


Я работаю с ASP.Net MVC3, более простой способ, чтобы использовать проверку клиента будет включение jquery.validate.unobtrusive. Все работает отлично, для вещей, которые прямо с сервера.

но когда я пытаюсь ввести некоторые новые "входы" с javascript, и я знал, что мне нужно позвонить $.validator.unobtrusive.parse() для повторной привязки проверок. Но все же, все эти динамические инжектированные поля не функционируют.

еще хуже, я пытаюсь вручную привязать с помощью jquery.validate и это не работает. Любой мысли?

11 97

11 ответов:

Я создал расширение для jquery.утверждать.ненавязчивый библиотека, которая решила эту проблему для моей ситуации - может быть интересно.

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

я попробовал подход Xhalent, но, к сожалению, он не работал для меня. Подход Робина работал и не работал. Он отлично работал для динамически добавляемых элементов, но если вы попытаетесь использовать JQuery для удаления всех атрибутов проверки и диапазонов из DOM, библиотека проверки все равно попытается проверить их.

однако, если вы удалите данные формы " unobtrusiveValidation "в дополнение к" validationData", он работал как шарм для динамического добавления и удаления элементы, которые вы хотите проверить или не проверить.

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

мне действительно очень нравится простота решения @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();

У меня такая же проблема. Я обнаружил, что это не возможно назвать $.валидатор.ненавязчивый.parse () на одной и той же форме дважды. При загрузке формы изначально с сервера форма автоматически анализируется ненавязчивой библиотекой. Когда вы добавляете элемент ввода динамически в форму и вызываете $.валидатор.ненавязчивый.parse () опять же, это не сработает. То же самое касается и parseElement().

ненавязчивый lib вызывает метод validate плагина jQuery validate для установки всех правила и сообщения. Проблема в том, что при повторном вызове плагин не обновляет новый набор правил.

Я нашел одно грубое решение: перед вызовом метода parse на ненавязчивой lib я выбрасываю валидатор формы:

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

теперь, когда метод validate вызывается ненавязчивой lib, все правила и сообщения воссоздаются, включая динамически добавленные входы.

надеюсь, что это помогает

Я использую MVC 4 и JQuery 1.8, похоже, что для включения jQuery для проверки динамически вводимого содержимого через Ajax или Jquery в DOM требуется следующий фрагмент кода.

Я сделал модульную функцию, которая принимает объект Jquery вновь добавленного элемента. Если вы клонировали новую таблицу с ID tblContacts используя Jquery по щелчку кнопки, затем включите функцию ниже в свой файл 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")

взяв из решения 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');

почему бы не использовать функции правила непосредственно из документа проверки 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');

Я нашел скрипт кода @Xhalent в своем коде и собирался удалить его, потому что я его не использовал, что привело меня к этому вопросу SO.

этот код довольно чистый и простой:

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();

Виола!

в случае динамического содержимого вам нужно обновить ненавязчивые проверки, как показано ниже, и проверить, если 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');
    }
});

я возился с этим некоторое время, ломая решения и пытаясь снова позже (когда у меня было свободное время, верьте или нет).

Я не уверен, что это поведение изменилось бы в более новых версиях jquery (мы используем 1.7.2), так как этот поток был создан или прокомментирован последним, но я обнаружил, что .parseElement(inputElement) отлично работает, когда я пытаюсь добавить динамически созданные элементы в форму, которая уже имеет загруженный валидатор. Это уже было предложено @jamesfm (15 февраля 11) в одном из комментариев выше, но я пропустил его в первые несколько раз, когда я работал над этим. Поэтому я добавляю его как отдельный ответ, чтобы сделать его более очевидным, и потому что я думаю, что это хорошее решение и не требует так много накладных расходов. Это может быть не актуально для всех вопросов, поднятых в последующих ответах, но я думаю, что это будет решение первоначального вопроса. Вот как я получил мою работу:

//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);

во-первых, я думаю, что вызов должен быть.валидатор, не проверяйте, тогда вам нужно передать идентификатор формы

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