简体   繁体   English

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

[英]TypeError: this.element is null, Rails with Judge gem

I am building simple client side valditation using Judge gem. 我正在使用Judge gem建立简单的客户端评估。

Everything worked perfect till I choosed to run validations on "blur" instead of button click. 在我选择对“模糊”运行验证而不是单击按钮之前,一切工作都非常完美。

Script: 脚本:

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(','));

        }

        });

      });

    }

In Mozzila Firebug there isn't any error message when I reload page. 在Mozzila Firebug中,当我重新加载页面时没有任何错误消息。 Error shows up when blur event is triggered. 触发模糊事件时显示错误。

Error message: 错误信息:

   TypeError: this.element is null

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

I don't understand why it crashes at second document.getElementById(divs[i]) instead of the first if that array is valid? 我不明白为什么它在第二个document.getElementById(divs[i])而不是第一个崩溃的情况下崩溃document.getElementById(divs[i])如果该数组有效)?

Any suggestions ? 有什么建议么 ?

Thanks 谢谢

The problem is that by the time the blur event fires, the for loop has exited and the value of i will be set to the last value it arrived at when the for loop exited. 问题在于,当blur事件触发时, for循环已退出,并且i的值将设置为for循环退出时到达的最后一个值。 Then, eventually, when the blur event fires judge.validate(document.getElementById(divs[i]) will fail because i is not what you expected. One way to fix it is by forming a closure over the value of i : 然后,最终,当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)
}

So we put the $.blur code inside a closure and pass i in. Inside the closure i will be called index . 因此,我们将$.blur代码放入闭包中并传递给i 。在闭包内, i将称为index The value of index will be the expected value at the time the loop executed the code, and will remain that way after the loop exits. index的值将是循环执行代码时的期望值,并在循环退出后保持该值。 Notice how inside the blur handler we're now using divs[index] . 注意我们现在在blur处理程序中如何使用divs[index]

The thing to take away from this particular problem is that the blur event handler function is asynchronous and won't evaluate divs[i] until the blur event happens which will be at a time after the for loop has exited and left the value of i at its last value i == arrayLength - 1 . 解决这个特定问题的方法是, blur事件处理程序函数是异步的,直到模糊事件发生(直到for循环退出并保留i的值)后,才会评估divs[i] 。在其最后一个值i == arrayLength - 1

Here's some more reading on that: Calling an asynchronous function within a for loop in JavaScript 这方面的更多信息: 在JavaScript中的for循环内调用异步函数

Another way to fix this would be to save the element you find with document.getElementById(divs[i]) and then use this inside the handler: 解决此问题的另一种方法是保存使用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(','));
      }
    });
  });
}

I'd choose the latter solution as it is cleaner. 我选择后一种解决方案,因为它更清洁。 Just wanted to explain the closure thing first. 只是想先解释一下关闭的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM