2014-09-27 2 views
0

질문 : 다음 설정에서 Angular "controller as"방법으로 $ scope를 삽입하지 않고 원하는 모델을 변경하는 방법이 있습니까?

HTML :

<div data-ng-controller="Buildings as vm"> 
    <select data-ng-model="vm.selected.building" 
      data-ng-options="building.name for building in vm.buildings" 
      data-ng-change="vm.changeBuilding()"> 
    </select> 
    <div data-ng-repeat="building in vm.buildings"> 
    <div data-ng-if="vm.selected.building.name === building.name"> 
     <select data-ng-model="vm.selected.room" 
       data-ng-options="room.name for room in building.rooms" 
       data-ng-change="vm.changeRoom()"> 
     <option value=""></option> 
     </select> 
    </div> 
    </div> 
</div> 

컨트롤러 :

angular.module('App').controller('Buildings', ['$scope', 'BuildingService', 'Geolocation', 
    function ($scope, BuildingService, Geolocation) { 
     var vm = this; 
     BuildingService.getAll().then(function (buildings) { 
      vm.buildings = buildings; 
      vm.selected = { // defaults 
       building: buildings[0], 
       room: null 
      }; 
     }); 
     if (navigator.geolocation) { 
      navigator.geolocation.getCurrentPosition(function (position) { 
       vm.selected.building = Geolocation.closest(position, vm.buildings); 
       vm.selected.room = null; 
       $scope.$apply(); // <--- Why is that needed? 
      }); 
     } 
     vm.changeBuilding = function() { 
      vm.selected.room = null; 
      console.log(vm.selected); 
     }; 
     vm.changeRoom = function() { 
      console.log(vm.selected); 
     }; 
    } 
]); 

설명 : I는 서비스로부터 건물의 배열을 가져, 다음 범위로 디폴트로 첫 번째 세트. 그런 다음 건물의 위도와 경도를 사용하여 현재 위치에 가장 가까운 건물을 계산하고 이에 따라 모형 개체를 변경합니다.

이 모두 작동합니다. 기본 건물은 첫 번째 HTML 선택 컨트롤에서 깜박이며 가장 가까운 건물로 변경됩니다.

그러나 일반적으로 컨트롤러가 필요하지 않기 때문에 "컨트롤러로"구문을 사용하고있을 때 $ scope를 컨트롤러에 삽입해야한다는 것을 알게되었습니다. $ scope을 꺼내면 알 수 있습니다. $ apply(); 선,보기가 변경되지 않습니다. vm.selected.building에 실제로 가장 가까운 것을 포함하고 있지만 여전히 기본 건물을 보여줍니다. (그리고 두 번째 html select에서 방을 선택하려고 시도하면 처음에는 vm.selected.building 모델 객체의 값으로 업데이트됩니다.

그래서이 이유는 무엇입니까? 주입없이 원하는 기능

편집 : 그래서 진짜 질문은 다음과 같습니다.? 왜 $의 범위를 호출해야 할 $ 여기) (적용하는 이유는보기없이 변경되지 않습니다 여기

+0

뷰에 항목을 표시하려면 $ scope가 필요합니다. 또한 사이드 노트와 같이, 의존성 삽입을 위해 배열 표기법을 사용할 필요가 없습니다. – alexrogins

+0

"controller as"구문을 사용할 때 명시 적으로 삽입 된 범위가없는보기에 항목이 표시됩니다. (http://www.johnpapa.net/angularjss-controller-as-and-the-vm-variable/) "controller as"를 사용하는 요점 중 하나를 올바르게 이해했다면 명시적인 $ scope injection이 필요하지 않습니다. – finn

+0

부수적으로, 설명서에서는 명시 적 $ inject 또는 배열 표기법을 사용하지 않으면 js가 코드를 중단한다는 것을 설명합니다. (http://code.angularjs.org/1.2.25/docs/guide/di) 그래서 나는 그것을 사용 해왔다. – finn

답변

1

를이 절에서? 콜백에서 vm.selected.building을 업데이트했습니다.

 navigator.geolocation.getCurrentPosition(function (position) { 
      /* See how this is a callback passed to getCurrentPosition that will be executed later */ 
      vm.selected.building = Geolocation.closest(position, vm.buildings); 
      vm.selected.room = null; 
      $scope.$apply(); // <--- Why is that needed? 
     }); 

apply()는 각 바인딩을 동기화합니다. 적용되는 대부분의 작업이 자동으로 호출되면 예 : 생성자 코드 이후 또는 대부분의 콜백 후에 각도 코드를 제공하십시오. 그러나 자동으로 $를 부르지 않는 제 3 자 라이브러리가있는 경우 직접해야합니다. 따라서 여기에 적용 할 수 있도록 범위를 주입해야합니다. 그렇지 않으면 navigator (전역 변수 인 것처럼 보입니다) 각도 서비스를 만들어이 한 번의 호출이 적용되도록해야합니다.

+0

감사합니다. 이해가가는 것 같네요. 나는 그 서비스를 만들기 위해 노력해야 할 것이다. 탐색기 변수는 브라우저에서 제공됩니다. 코드에서 아무 곳이나 만들지 않습니다.http://www.w3schools.com/html/html5_geolocation.asp – finn

관련 문제