2015-01-14 4 views
1

나는 판사 보석을 사용하여 간단한 클라이언트 측 valditation을 구축 중입니다.TypeError : this.element는 null, Rails with Judge gem

버튼 클릭 대신 "흐림"에 대한 유효성 검사를 실행하기 전까지 모든 것이 완벽하게 작동했습니다.

스크립트 : 내가 페이지를 다시로드 할 때 Mozzila 파이어 버그에서

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

     } 

     }); 

     }); 

    } 

오류 메시지가 없습니다. 흐림 이벤트가 발생하면 오류가 표시됩니다.

오류 메시지 : 대신 해당 배열이 유효한 경우 최초의 초 document.getElementById(divs[i])에 충돌하는 이유

TypeError: this.element is null 

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

이해가 안?

제안 사항?

감사

답변

2

문제는 시간에 의해 blur 이벤트가 발생이의 for 루프를 종료하고 i의 값은 (는) for 루프 종료시에 도착 마지막 값으로 설정 될 것입니다. 그렇다면 이벤트가 발생하면 이 실패합니다. 이는 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 내부 index를 호출됩니다.. index의 값은 루프가 코드를 실행 한 시점의 예상 값이며 루프가 종료 된 후에도 그대로 유지됩니다. blur 핸들러 내부에서 우리가 현재 divs[index]을 어떻게 사용하고 있는지 주목하십시오.

이 특정 문제에서 빼앗아하는 것은 blur 이벤트 핸들러 함수가 비동기 및 흐림 이벤트가 for 루프가 종료되고의 값을 떠난 후 한 번에 할 것이다 일어날 때까지 divs[i]을 평가하지 것입니다 i의 마지막 값은 i == arrayLength - 1입니다.

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

내가 선택한 것 : 당신이 document.getElementById(divs[i])으로 찾을 수있는 요소를 저장 한 다음 핸들러 내부 this을 사용하는 것이 문제를 해결하는 Calling an asynchronous function within a for loop in JavaScript

또 다른 방법 :

여기에 그 몇 가지 더 읽기입니다 후자의 해결책은 깨끗합니다. 먼저 물건을 먼저 설명하고 싶었습니다.

+0

고맙습니다. 나는 이것에 대해 더 많은 평판을 줄 수 있었으면 좋겠다. – Edgars

+1

내 기쁨 :-) – DiegoSalazar

+1

핸들러에서'$ (document) .getElementById (divs [i])'대신'this'를 사용하는 것이 더 쉬울까요? 또한 현재 논리는 많은 핸들러를 생성 할 것이므로 이벤트를 위임하는 것이 더 효율적입니다. – BroiSatse