2014-04-16 12 views
1

사용자가 데이터를 서버에 다시 저장하지 않고 탐색하지 못하도록하는 양식이 있습니다. here에서 $locationChangeStart 이벤트에 리스너를 추가 할 수있는 코드를 빌려 왔습니다. 내 양식에 대한 컨트롤러에 다음 코드를 넣고, 보라, 아무 일도 일어나지 않았다.

var cancelRouteListener = $rootScope.$on('$locationChangeStart', checkForUnsavedData); 

    function checkForUnsavedData (event, newURL) { 
     if (!$scope.form.$dirty) { 
      return; 
     } 

     var proceed = $window.confirm('The page has unsaved changes. Do you want to continue?'); 

     if (proceed) { 
      cancelRouteListener(); 
      $location.path(newURL); 
     } 

     event.preventDefault(); 
     return; 
    } 

나는 $location.path()에 대한 호출에 도달하는 코드를 볼 수 있지만 페이지 탐색은 변경되지 않았다.

$rootScope.$apply(function() { 
    $location.path(newURL); 
} 

소호을하고 일이, 보라 : 그럼, 절망에서, $rootScope.$apply()에 호출 코드의 라인을 포장했습니다. 몇 가지 질문이 있습니다.

  1. .$apply() 기능을 사용해야하는 이유는 무엇입니까? 코드가 $ rootScope의 컨텍스트에서 실행될 것이라고 생각했습니다.
  2. $rootScope에 첨부해야합니까? 양식의 경로가 활성화 된 경우에만이 수신기가 필요합니다.

답변

2

먼저, $apply()을 의미하지 않습니까? 둘째로 컨트롤러 내에서 $scope 대신에 $rootScope을 사용하여 다이제스트주기를 시작하는 이유는 무엇입니까? 셋째, 원하는 기능을 수행하기 위해 올바른 논리를 사용하지 않는다고 생각합니다. 이벤트 $locationChangeStart은 각도 어플리케이션 내의 위치 변경의 시작을 알립니다. $window.confirm()은 해당 내비게이션을 일시적으로 중지하고 event.preventDefault()을 호출하면 탐색이 모두 중지됩니다. 따라서 확인을 위해 $window.confirm()에서 기다려야합니다. 클릭 사용이 취소되면 proceed은 false가됩니다. proceed이 거짓이면 event.preventDefault()으로 전화하고 그렇지 않으면 아무 것도하지 않습니다. 응용 프로그램이 이미 해당 페이지로 이동하는 과정에있는 경우 $location.path()으로 전화 할 필요가 없습니다. 내가 여기에 시나리오의 쿵하는 소리를 만든

:

http://plnkr.co/edit/qfRVDtIlKqQ1p0pZ4oZ1?p=preview

+0

첫째, 그래, 나는'$ 적용 것을 의미()'. 둘째로, 나는 그것이 내가 처음 만난 첫 번째 옵션 이었기 때문에 그렇게했다. 나는 그것을 할 필요가 있다고 생각하지 않기 때문에 여기에 게시하고있다. 왜 그런지 이해하고 싶다. 셋째, 논리로 말하는 것을 봅니다. 왜냐하면 내가하는 일이 불필요하기 때문입니다. 그러나 그것은 내가 찾던 답변이 아닙니다. –

+1

좋아. '$ rootScope. $ apply()'는 전혀 필요하지 않으며, 사실 가능하지도 않습니다. 만약 컨트롤러 내에서이 로직을 실행한다면'$ locationChangeStart'가 브로드 캐스트 이벤트이고 모든 자식 스코프로 향하기 때문에'$ rootScope. $ on' 대신'$ scope. $ on'을 호출해야합니다 . 그것은 당신에게 의존성 주입을 저장합니다. 이벤트 리스너는 항상 다이제스트주기 내에서 호출되므로이 작업을 수행 할 수 없습니다. '$ apply()'를 호출하면 응용 프로그램이 중단됩니다. 컨트롤러는 어떻게 정의됩니까? – Mike

+0

내 컨트롤러는 내 모듈 객체에서'.controller()'메서드를 사용하여 정의됩니다. 이것이 의미하는 바라면 전역 네임 스페이스에 없습니다. 나는 당신이 말하는 것을 이해하고 있다고 생각합니다 -'$ rootScope'에'$ apply()'를 사용하면 많은 문제가 발생할 수 있습니다. 컨트롤러의 하위 범위를 사용하도록 코드를 리팩터링했습니다. 내가 아주 불규칙하게 코딩 된 예제를 따르려고하는 것처럼 들리므로, 나는 나쁜 습관으로 그것을 분필 할 것이고, 지금부터 당신이 제안한 방식대로 할 것이다. 감사! –