ASP.NET MVC 3 Ненавязчивый Jquery Validate не показывает настраиваемые сообщения об ошибках более одного раза - PullRequest
2 голосов
/ 28 марта 2012

Итак, я взял некоторый код из этого примера, предоставленного Microsoft , который позволяет мне использовать ненавязчивую библиотеку jquery validate для анализа сообщения об ошибке проверки, возвращенного с моего сервера, и отображения их в пользовательском интерфейсе. У них есть видео, демонстрирующее это . Итак, вот фрагмент кода Javascript, который я использую:

   $.validator.addMethod("failure", function () { return false; });
    $.validator.unobtrusive.adapters.addBool("failure");
    $.validator.unobtrusive.revalidate = function (form, validationResult) {
        $.removeData(form[0], 'validator');
        var serverValidationErrors = [];
        for (var property in validationResult) {
            //var elementId = property.toLowerCase();
            var item = form.find('#' + property);
            if (item.length < 1) { item = form.find('#' + property.replace('.', '_')); }
            serverValidationErrors.push(item);
            item.attr('data-val-failure', validationResult[property].join(', '));
            jQuery.validator.unobtrusive.parseElement(item[0]);
        }
        form.valid();
        $.removeData(form[0], 'validator');
        $.each(serverValidationErrors, function () {
            this.removeAttr('data-val-failure');
            jQuery.validator.unobtrusive.parseElement(this[0]);
        });
    };

Итак, после публикации формы AJAX в функции ошибки дескриптора, я бы сделал что-то вроде этого:

$.validator.unobtrusive.revalidate(form, { 'PhysicalAddress.CityName': ['You must select a valid city'] });

Где PhysicalAddress.CityName - это имя моего свойства viewmodel и поля ввода html. Таким образом, он знает, чтобы поместить сообщение проверки рядом с правильным элементом HTML.

Это работает 1 раз. Затем, когда они снова нажимают «Отправить», и мой код снова вызывает метод unobtrusive.revalidate , он не работает. Оно показывает сообщение проверки только один раз, после чего сообщение проверки исчезает навсегда.

Кто-нибудь имеет какие-либо идеи относительно того, почему это может происходить? .. Я прошел через метод revalidate, и не было выдано никаких ошибок, и все кажется, что оно должно работать ... но ненавязчивая библиотека по какой-то причине не привязывается повторно сообщение об ошибке проверки.

Спасибо

1 Ответ

3 голосов
/ 01 апреля 2012

Вероятно, это поведение зависит от известной проблемы плагина проверки jQuery: динамическое добавление новых правил проверки для элементов работает только один раз!Дальнейшие попытки отклоняются, потому что плагин думает, что они являются дублированной попыткой определить уже определенные правила.

Это причина, почему $.validator.unobtrusive.parse не работает, когда вы добавляете только что созданный контент (например, когда выдобавить новую строку в коллекцию предметов).Для $.validator.unobtrusive.parse есть патч, который вы можете попробовать применить и к функции revalidate .... но лучше переписать его с нуля другим способом.Функция revalidate использует плагин валидации, чтобы просто разместить в нужном месте все ошибки валидации, а затем пытается сбросить состояние плагина валидации.Однако удаления объекта валидатора из формы недостаточно для отмены всей выполненной работы, поскольку в form.data('unobtrusiveValidation') содержится другой объект, где форма - это переменная, содержащая проверяемую форму ... Эти данные не сбрасываются при повторной проверкеФункция ... и НЕ МОЖЕТ быть сброшена, поскольку их сброс приведет к отмене ВСЕХ правил проверки на стороне клиента.

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

Если это не решит вашу проблему, я могу передать вам аналогичную функцию, реализованную совершенно другим способом (она имитирует то, что сервер делает на стороне сервера, чтобы показать ошибки на стороне сервера).Он будет содержаться в следующей версии инструментария Mvc Controls.Однако, если вы дадите мне пару дней (я буду очень занят в течение 2 дней), я могу извлечь его оттуда с его зависимостями, чтобы вы могли его использовать.Дайте мне знать, если вы заинтересованы.

Ниже кода, который я обещал.Он ожидает массив, элементы которого:

{
    id:id of the element in error
    errors:array of strings errors associated to the element
}

Он принимает несколько ошибок для каждого элемента, но просто отображает di первый для каждого элемента, идентификатор которого отличается от имени, потому что.[] другой специальный символ заменяется на _

. Вы можете преобразовать имя в id на сервере с помощью

htmlName.Replace('$', '_').Replace('.', '_').Replace('[', '_').Replace(']', '_');

или на клиенте в javascript с помощью:

name.replace(/[\$\[\]\.]/g, '_');

function remoteErrors(jForm, errors) {
    //////////
    function inner_ServerErrors(elements) {
        var ToApply = function () {
            for (var i = 0; i < elements.length; i++) {
                var currElement = elements[i];
                var currDom = $('#' + currElement.id);
                if (currDom.length == 0) continue;
                var currForm = currDom.parents('form').first();
                if (currForm.length == 0) continue;

                if (!currDom.hasClass('input-validation-error'))
                    currDom.addClass('input-validation-error');
                var currDisplay = $(currForm).find("[data-valmsg-for='" + currElement.name + "']");
                if (currDisplay.length > 0) {
                    currDisplay.removeClass("field-validation-valid").addClass("field-validation-error");
                    replace = $.parseJSON(currDisplay.attr("data-valmsg-replace")) !== false;
                    if (replace) {
                        currDisplay.empty();
                        $(currElement.errors[0]).appendTo(currDisplay);
                    }
                }
            }
        };
        setTimeout(ToApply, 0);
    }
    /////////
    jForm.find('.input-validation-error').removeClass('input-validation-error');
    jForm.find('.field-validation-error').removeClass('field-validation-error').addClass('field-validation-valid');
    var container = jForm.find("[data-valmsg-summary=true]");
    list = container.find("ul");
    list.empty();
    if (errors.length > 0) {
        $.each(errors, function (i, ival) {
            $.each(ival.errors, function (j, jval) {
                $("<li />").html(jval).appendTo(list);
            });

        });
        container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
        inner_ServerErrors(errors);
        setTimeout(function () { jForm.find('span.input-validation-error[data-element-type]').removeClass('input-validation-error') }, 0);
    }
    else {
        container.addClass("validation-summary-valid").removeClass("validation-summary-errors");
    }
}
function clearErrors(jForm) {
    remoteErrors(jForm, []);
}
...