Jquery.validate.unobtrusive не работает с динамическими инъецированными элементами

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

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

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

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

Надеюсь, что это поможет

Ответ 5

Я использую 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")

Ответ 6

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

Ответ 7

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

Ответ 8

Я нашел @Xhalent код script в своем коде и собираюсь удалить его, потому что я не использовал его, что привело меня к этому вопросу 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();

Viola!

Ответ 9

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

Ответ 10

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

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

Ответ 11

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

Я не уверен, изменилось бы это поведение в новых версиях jquery (мы используем 1.7.2), поскольку этот поток был создан или прокомментирован последним, но я обнаружил, что .parseElement(inputElement) отлично работает, когда я пытаюсь добавить динамически созданных элементов в форму, на которой уже загружен валидатор. Это уже было предложено @jamesfm (Feb 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);

Ответ 12

Я пробовал отвечать на виггит, и сначала все, казалось, сработало. Но через некоторое время я заметил, что валидация становится болезненно медленной, чем более динамически добавляемые элементы. Причина заключалась в том, что его решение не отвязывает обработчики событий, но каждый раз добавляет новые. Поэтому, если вы добавите 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");