jquery.validate.unobtrusive не працює з динамічно введеними елементами


99

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

Але коли я намагався ввести деякі нові "входи" за допомогою JavaScript, я знав, що мені потрібно зателефонувати, $.validator.unobtrusive.parse()щоб відновити перевірки. Але все-таки всі ці динамічно введені поля не функціонують.

Ще гірше, я намагаюся вручну зв’язати використання, jquery.validateі воно також не працює. Будь-які думки?


1
Якщо ви прийшли сюди з google, ви, ймовірно, шукаєте відповідь @Sundara Prabu, оскільки інші, які масово оцінюються, старі.
The Muffin Man

Відповіді:


65

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

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


Я думаю, я повинен проголосувати вашу відповідь як правильну. BTW, чи працює ваша бібліотека з найновішим MVC RC? або вони це просто виправили?
xandy

1
Використовуючи приєднаний вище код, не забудьте оновити його, щоб включити код у коментарі, інакше він може зламатися. Зокрема, змініть дві селекторні лінії, щоб подвоїти котирування ідентифікатора.
Райан О'Нілл

1
Нарешті вдалося змусити це працювати за моїм сценарієм після деякої налагодження. Здається, він повинен переходити не в селектор введення, але батьківський вхід або форму через виклик до $.validator.unobtrusive.parse(). Крім того, схоже, вони додають лише нові правила, але не підбирають оновлення до існуючих правил?
ламбінатар

5
Ця відповідь повинна містити принаймні ведмежі кістки допису в блозі. Відповіді лише на посилання, як правило, поза темою для SO
Ліам

8
Хоча ця відповідь 3+ років було б вкрай корисно , якби ви могли відправити основні частини відповіді тут, на цьому сайті, або ваше повідомлення ризикує бути видалений Дивіться FAQ , де він згадує відповіді, які «навряд чи більше , ніж посилання '. Ви можете все-таки включити посилання за бажанням, але лише як "довідник". Відповідь має стояти самостійно, не потребуючи посилання.
Taryn

159

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

Однак якщо ви видалите дані "ненав’язливої ​​валідації" форми на додаток до "validationData", це буде працювати як шарм для динамічного додавання та видалення елементів, які ви хочете перевірити чи не підтвердити.

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

2
Спочатку Xhalent для мене також не працював, потім я помітив, що для розбору слід передавати контейнер для нових елементів, а не самі елементи - швидке виправлення було б передати всю форму замість елементів (елементів) - тоді це працював як шарм.
Per Hornshøj-Schierbeck

1
будь-яка ідея, чому вона говорить validator, не визначена? Я маю на увазі і валідацію, і валідацію. Перевірка працює, поки я не зателефоную до цього коду
Shawn Mclean

4
Дякую. Він працює для вмісту, доданого на сторінку в часткових переглядах ASP.MVC, доданих через виклик AJAX.
Максим Козленко

Завдяки цьому допомогло. Але я зіткнувся з проблемою, коли я використовую гармошки на сторінці, і якщо гармошка згорнута, вона не запускає перевірки. Як я можу це виправити? Я знаю, якби я пішов на звичайний модуль jquery validate замість ненав’язливого MVC3, я повинен був сказати$('#form').validate({ignore: ""})
парш

1
Це працювало для мене в PHP. просто додаючи цю інформацію, оскільки кожен коментар вказує на .NET MVC. : P
finnTheHumin

42

Мені справді дуже подобається простота @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();

замінити $ .validator.unobtrusive.parse ("#" + form.attr ("id")); з $ .validator.unobtrusive.parse (форма);
Softlion

ви також можете безпечно видалити .first (), оскільки найближчий повертає лише 1 елемент.
Softlion

Приємно, мені подобається такий простий підхід
nixon

Прекрасно працює як для додавання, так і для видалення атрибутів data-val
Джуліан Дормон

33

У мене така ж проблема. Я виявив, що неможливо викликати $ .validator.unobtrusive.parse () у тій самій формі двічі. При завантаженні форми спочатку з сервера форма аналізується автоматично ненав'язливою бібліотекою. Якщо динамічно додавати вхідний елемент до форми і знову викликати $ .validator.unobtrusive.parse (), він не працюватиме. Те саме стосується parseElement ().

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

Я знайшов одне неочищене рішення: Перш ніж викликати метод розбору на ненав'язливій lib, я викидаю валідатор форми:

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

Тепер, коли метод валідації викликається ненав'язливою lib, усі правила та повідомлення відтворюються, включаючи вводи, що динамічно додаються.

Сподіваюся, це допомагає


Заслуговує +1 - це сире рішення, як ви сказали самі, але цілком зрозуміло, що він робить і в якому стані ви залишилися після цього
Пер Хорншой-Ширбек

2
З блогу Бреда Вілсона: "Ви також можете зателефонувати на функцію jQuery.validator.unobtrusive.parseElement () для розбору одного елемента HTML." Будь-яка допомога?
jamesfm

@Per Hornshøj-Schierbeck: @ Robin van der Knaap: Я витратив останні 2-3 години, щоб зрозуміти це !! У будь-якому випадку - це спрацювало ЧУДОВО. Сире змушує мене відчувати, що я не повинен його використовувати, чому я б не хотів цього робити?
KTF

2
Рішення є дещо неочищеним, тому що всі валідатори видаляються та знову відновлюються, включаючи динамічно доданий валідатор. Було б краще, якби оновлювався лише динамічно доданий валідатор. @Xhalent пропонує більш чітке рішення у своїй відповіді, але в основному ненав’язлива бібліотека з MS повинна бути оновлена ​​для цього сценарію.
Робін ван дер Кнаап

9

Я використовую 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")

currform.validate (); насправді має бути currForm.validate (); (друкарська помилка). Дякуємо за те, що поділилися, але це працювало для мене
Джон Мак-

1
@JohnMc виправила друкарську помилку
Sundara Prabu

Це єдиний, хто працював на мене (mvc 4 та jquery 1.10)
The Muffin Man

4

Чому б не використовувати функцію правил безпосередньо з документа дозволу 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

Беручи з рішення 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');

1

Я знайшов сценарій коду @ 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();

Віола!


1

Я спробував відповісти на пильність і спочатку все, здавалося, спрацювало. Але через деякий час я помітив, що валідація стає болісно сповільнювати більш динамічні елементи, які я додав. Причина полягала в тому, що його рішення не розв’язує обробників подій, а додає нові щоразу. Тож якщо ви додасте 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

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

0

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

Я не впевнений, чи змінилася б така поведінка в новіших версіях 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);

0

По-перше, я думаю, виклик повинен бути .validator, а не валідація, тоді вам потрібно передати ідентифікатор форми

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

Я припускаю, що ви завантажили і jquery.validate & jquery.validate.unobtrusive сценарії та назвали Html.EnableClientValidation () та Html.EnableUnobtrusiveJavaScript () методами? Чи можете ви опублікувати зразок коду для вашої базової сторінки та, можливо, динамічно завантаженої форми?
Кріс Олмарк

0

Якщо вам потрібно додати та видалити речі з можливістю відображення деяких помилок, це те, з чим я прийшов. Він заснований в основному на різних ідеях на цій сторінці запитань. Я використовую вбудований 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);

Примітка: Якщо деякі або всі вхідні дані були підтверджені і мають помилки, ці помилки будуть скинуті ... але вони будуть правильно повертатися при наступній валідації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.