2010-03-08 55 views
10

我使用jQuery验证插件,并希望使用errorPlacement功能错误信息添加到字段标题属性,显示只是一个✘该字段旁边。jQuery的验证插件:调用errorPlacement功能时onfocusout在,KEYUP并单击

当表单被提交按钮提交,但出现以下任一事件被触发这个伟大的工程: - onfocusout在 - 点击 - 的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" 
}); 

回答

16

你的问题是,该插件仅适用于被验证的每个元素调用errorPlacement函数一次。 Namly当第一次创建该元素的错误标签。此后该插件只会重复使用已存在的标签,只是替换里面的HTML(或隐藏错误标签如果元素是现在有效)。这就是为什么你的十字架被移除,显示实际的错误信息。

只是为了确保该插件的流程清晰。

  1. 元(不errorlabel还)
  2. 元素在某些时候
  3. 插件创建错误的标签,并呼吁errorPlacement功能
  4. 元素“跨界”(标题中的错误消息)
  5. 元素获得得到确认重点和你改变的东西
  6. 插件重新验证元素
  7. 看到错误标签已被创建(并放置)
  8. 插件只是调用的label.html(message)不是删除旧标签和readding它

所以你看,你的问题是一种优化的插件不保存错误标签的一些不必要的,插入/移除。这也是有道理的。

您可以检查我说在功能查看确认,插件,源代码

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(); 
    } 
... 
}); 

线条也许有一个更清洁的解决方案,这一点,但这个应该这样做,给你时间去调查一个更好的解决方案。

+0

帮助........ :) – 2015-05-29 13:05:56

1

感谢抖动

我做了一些挖了一圈,发现了同样的问题。

我设法通过“hacking”jquery.validation.js中的showLabel函数来实现它。这不是漂亮,但工程。

覆盖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); 
     }