TypeError:this.element为null,Rails与Judge gem

时间:2015-01-14 15:31:01

标签: javascript jquery ruby-on-rails

我正在使用Judge gem构建简单的客户端边界。

一切都很完美,直到我选择在"模糊"上运行验证。而不是点击按钮。

脚本:

var divs = ["advertisement_age","advertisement_weight","advertisement_region_id","advertisement_height","advertisement_name","advertisement_phone_number","Record_Start_Time",
"Record_End_Time","Record_Start_Time2","Record_End_Time2","advertisement_description", "advertisement_description_ru", "advertisement_terms_of_service"];

    var arrayLength = divs.length;
    var error_count =0;
    for (var i = 0; i < arrayLength; i++) {

     $(document.getElementById(divs[i])).blur(function(){

        judge.validate(document.getElementById(divs[i]), {  // This line causes error
                valid: function(element) {
                  element.style.border = '1px solid green';
                },
                invalid: function(element, messages) {
                  element.style.border = '1px solid red';
                 // alert(messages.join(','));

        }

        });

      });

    }

在Mozzila Firebug中,当我重新加载页面时,没有任何错误消息。 触发模糊事件时会出现错误。

错误讯息:

   TypeError: this.element is null

   this.attrValidators = root.JSON.parse(this.element.getAttribute('data-validate')...

如果该数组有效,我不明白为什么它会在第二个document.getElementById(divs[i])而不是第一个崩溃?

有什么建议吗?

由于

1 个答案:

答案 0 :(得分:2)

问题是,当blur事件触发时,for循环已退出,i的值将设置为for时的最后一个值{退出{1}}循环。然后,最终,blur事件触发judge.validate(document.getElementById(divs[i])将失败,因为i不是您所期望的。修复它的一种方法是在i

的值上形成一个闭包
for (var i = 0; i < arrayLength; i++) {
  (function(index) { // index is the current i value
    $(document.getElementById(divs[index])).blur(function() {
      judge.validate(document.getElementById(divs[index]), {
        valid: function(element) {
          element.style.border = '1px solid green';
        },
        invalid: function(element, messages) {
          element.style.border = '1px solid red';
          // alert(messages.join(','));
        }
      });
    });
  })(i); // pass i to the immediately executing anonymous function (closure)
}

因此我们将$.blur代码放在一个闭包中并传递i。在闭包i内将调用indexindex的值将是循环执行代码时的预期值,并且在循环退出后将保持该值。请注意blur处理程序内部我们现在使用divs[index]的方式。

要解决这个特殊问题的一点是,blur事件处理函数是异步的,并且不会评估divs[i],直到模糊事件发生,这将发生在for循环已退出,并将i的值保留为其最后一个值i == arrayLength - 1

此处还有更多内容:Calling an asynchronous function within a for loop in JavaScript

解决此问题的另一种方法是使用document.getElementById(divs[i])保存您找到的元素,然后在处理程序中使用this

for (var i = 0; i < arrayLength; i++) {
  var field = $(document.getElementById(divs[i]));
  field.blur(function() {
    judge.validate(this, { // `this` is the field element
      valid: function(element) {
        element.style.border = '1px solid green';
      },
      invalid: function(element, messages) {
        element.style.border = '1px solid red';
        // alert(messages.join(','));
      }
    });
  });
}

我选择后一种解决方案,因为它更清洁。只是想先解释封口的事情。