jquery.validate.unobtrusive не работает с динамически внедренными элементами - PullRequest
97 голосов
/ 10 декабря 2010

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

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

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

Ответы [ 12 ]

154 голосов
/ 26 апреля 2011

Я попробовал подход Ксалента, но, к сожалению, он не сработал для меня.Подход Робина сработал и не сработал.Он отлично работал для динамически добавляемых элементов, но если вы попытались использовать JQuery для удаления всех атрибутов валидации и диапазонов из DOM, библиотека валидации все равно будет пытаться их проверить.Данные «unobtrusiveValidation» в дополнение к «validationData», они работали как талисман для динамического добавления и удаления элементов, которые вы хотите проверить или не проверить.

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
66 голосов
/ 24 января 2011

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

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

40 голосов
/ 27 октября 2011

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

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

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

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

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

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

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

8 голосов
/ 28 февраля 2013

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

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

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

Взяв решение 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 и хотите, чтобы эти правила валидации также были удалены, вызовите:

$.validator.unobtrusive.unparseContent('input.something');
1 голос
/ 10 февраля 2016

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

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

Я нашел код сценария @ 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!

...