jquery.validate.unobtrusive не работает с динамически внедренными элементами
Я работаю с ASP.Net MVC3
более простым способом использования проверки клиента будет включение jquery.validate.unobtrusive
, Все работает отлично, для вещей, которые прямо с сервера.
Но когда я пытаюсь ввести некоторые новые "входы" с помощью JavaScript, и я знал, что мне нужно позвонить $.validator.unobtrusive.parse()
повторно связать проверки. Но все же, все эти динамические введенные поля не функционируют.
Еще хуже, я пытаюсь вручную связать с помощью jquery.validate
и это тоже не работает. Какие-нибудь мысли?
12 ответов
Я создал расширение для библиотеки jquery.validate.unobtrusive, которое решило эту проблему для моей ситуации - это может представлять интерес.
http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/
Я попробовал подход Ксалента, но, к сожалению, он мне не помог. Подход Робина сработал и не сработал. Это отлично работает для динамически добавляемых элементов, но если вы попытаетесь использовать 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();
У меня та же проблема. Я обнаружил, что дважды невозможно вызвать $.validator.unobtrusive.parse() в одной и той же форме. При первоначальной загрузке формы с сервера форма автоматически анализируется ненавязчивой библиотекой. Когда вы динамически добавляете элемент ввода в форму и снова вызываете $.validator.unobtrusive.parse(), он не будет работать. То же самое касается parseElement().
Ненавязчивая lib вызывает метод validate плагина jquery validate для установки всех правил и сообщений. Проблема в том, что при повторном вызове плагин не обновляет новый набор правил.
Я нашел одно грубое решение: перед вызовом метода синтаксического анализа в ненавязчивой lib, я выбрасываю валидатор формы:
$('yourForm').removeData("validator");
Теперь, когда метод validate вызывается ненавязчивой библиотекой, все правила и сообщения воссоздаются, включая динамически добавленные входные данные.
Надеюсь это поможет
Я использую 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")
Я попробовал ответ Виггити, и сначала все, казалось, работало. Но через некоторое время я заметил, что проверка становится мучительно медленнее, чем динамически добавляются элементы, которые я добавил. Причина в том, что его решение не отменяет привязку обработчиков событий, а добавляет новые каждый раз. Таким образом, если вы добавляете 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");
Почему бы не использовать функцию правил непосредственно из документа проверки 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, помеченное как ответ выше, я немного расширил его.
$.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');
Я нашел код сценария @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();
Виола!
В случае динамического содержимого вам необходимо обновить ненавязчивые проверки, как показано ниже, и проверить, если 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);
Если вам нужно добавить или удалить что-то с возможностью того, что некоторые ошибки уже отображаются, я пришел с этим. Он основан в основном на разных идеях на этой странице вопроса. Я использую встроенный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);
Примечание. Если некоторые или все входные данные были проверены и содержат ошибки, эти ошибки будут сброшены... но они вернутся правильно при следующей проверке.
Во-первых, я думаю, что вызов должен быть.validator, а не подтверждать, тогда вам нужно передать идентификатор формы
$.validator.unobtrusive.parse("#id");