jQuery Validation Plugin: Вызвать функцию errorPlacement, когда onfocusout, keyup и нажмите - PullRequest
10 голосов
/ 08 марта 2010

Я использую плагин проверки jquery и хочу использовать функцию errorPlacement, чтобы добавить сообщения об ошибках в атрибут заголовка поля и отобразить только ✘ рядом с полем.

Это прекрасно работает, когда форма отправляется с помощью кнопки отправки, но когда запускается любое из следующих событий: - на фокусе - нажмите - onkeyup

Проверочные проверки выполняются, но она пропускает функцию errorPlacement и добавляет полное сообщение об ошибке после поля, как поведение по умолчанию.

Я использую следующий код:

$("#send-mail").validate({
    debug: true,
    // set this class to error-labels to indicate valid fields 
    success: function(label) {
        // set text as tick
        label.html("✔").addClass("valid"); 
    }, 
     // the errorPlacement has to take the table layout into account 
    errorPlacement: function(error, element) {
        console.log("errorPlacement called for "+element.attr("name")+" field");
        // check for blank/success error
        if(error.text() == "")
        { 
            // remove field title/error message from element
            element.attr("title", "");
            console.log("error check passed");
        }
        else
        {
            // get error message
            var message = error.text();

            // set as element title
            element.attr("title", message);

            // clear error html and add cross glyph
            error.html("✘"); 

            console.log("error check failed: "+message);
        }
        // add error label after form element
        error.insertAfter(element);
    },
    ignoreTitle: true,
    errorClass: "invalid"
});

Ответы [ 2 ]

17 голосов
/ 08 марта 2010

Ваша проблема в том, что плагин вызывает функцию errorPlacement только один раз для каждого проверяемого элемента. Namly, когда метка ошибки для элемента создается впервые. После этого плагин просто повторно использует уже существующую метку и просто заменяет html внутри (или скрывает метку ошибки, если элемент теперь допустим). Вот почему ваш крест удаляется и отображается фактическое сообщение об ошибке.

Просто чтобы убедиться, что плагин чист.

  1. элемент (без метки ошибки)
  2. элемент проверяется в какой-то момент
  3. плагин создает метку ошибки и вызывает errorPlacement функцию
  4. элемент "крест" (сообщение об ошибке в заголовке)
  5. Элемент получает фокус, и вы что-то меняете
  6. плагин повторно проверяет элемент
  7. Видит, что метка ошибки уже была создана (и размещена)
  8. плагин просто вызывает label.html(message) вместо удаления старой метки и чтения ее

Итак, вы видите, что ваша проблема - это своего рода оптимизация, которую выполняет плагин, чтобы сохранить некоторые ненужные вставки / удаления меток ошибок. Что тоже имеет смысл.

Вы можете проверить, что я сказал, посмотрев на validation-plugin-sourcecode

jquery.validate.js v1.6 проверка в функции showLabel строки 617-625 для соответствующих частей.


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

Что-то вроде

$("#send-mail").validate({
...
    showErrors: function(errorMap, errorList) {
        for (var i = 0; errorList[i]; i++) {
            var element = this.errorList[i].element;
            //solves the problem with brute force
            //remove existing error label and thus force plugin to recreate it
            //recreation == call to errorplacement function
            this.errorsFor(element).remove();
        }
        this.defaultShowErrors();
    }
...
});

Может быть, есть более чистое решение для этого, но это должно сделать это и дать вам время, чтобы найти лучшее решение.

1 голос
/ 08 марта 2010

Спасибо Джиттер ,

Я немного покопался и нашел ту же проблему.

Мне удалось заставить его работать, "взломав" функцию showLabel в jquery.validation.js. Это не красиво, но работает.

Переопределение опции функции showErrors не позволило бы мне изменить код плагина, поэтому я посмотрю.

Вот код, который я использовал для метода showLabel:

     showLabel: function(element, message) {

            // look for existing error message
            var label = this.errorsFor( element );
            // existing error exist?
            if (label.length) {
                // refresh error/success class
                label.removeClass().addClass( this.settings.errorClass );

                // check if we have a generated label, replace the message then
                label.attr("generated");

                // is message empty?
                if(!message)
                {
                    // add tick glyph
                    label.html("✔");

                    // wipe element title
                    $(element).attr('title', message)
                }
                else
                {
                    // clear error html and add cross glyph
                    label.html("✘");

                    // update element title
                    $(element).attr('title', message)
                }

                // && label.html(message);
            } 
            else {
                // create label
                label = $("<" + this.settings.errorElement + "/>")
                    .attr({"for":  this.idOrName(element), generated: true})
                    .addClass(this.settings.errorClass)
                    .html(message || "");
                if ( this.settings.wrapper ) {
                    // make sure the element is visible, even in IE
                    // actually showing the wrapped element is handled elsewhere
                    label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
                }
                if ( !this.labelContainer.append(label).length )
                    this.settings.errorPlacement
                        ? this.settings.errorPlacement(label, $(element) )
                        : label.insertAfter(element);
            }
            if ( !message && this.settings.success ) {
                label.text("");
                typeof this.settings.success == "string"
                    ? label.addClass( this.settings.success )
                    : this.settings.success( label );
            }
            this.toShow = this.toShow.add(label);
        }
...