2014-09-09 4 views
10

Obecnie używam formatu Controller As do kontrolowania zakresu.

To działa doskonale, aby zachować przejrzystość i łatwość śledzenia zakresu wartości na widokach.

<div ng-app="myApp" ng-controller="myController as myctrl"> 
    <ul> 
     <li ng-repeat="contact in myctrl.contacts"> 
      <input type="text" ng-model="contact.name.first" /> 
     </li> 
    </ul> 
</div> 

Jednakże, gdy wdrożenie $watch używam do problemów, ponieważ wydaje się być zależna od $scope więc dodaje nie będzie działać.

angular.module('myApp',[]) 
.controller('myController',['contacts',function(contacts) { 
    this.contacts = contacts; 

    this.$watch('contacts', function(newValue, oldValue) { 
     console.log({older: oldValue, newer:newValue}); 
    }); 

}]); 

uzyskać niezdefiniowane nie jest funkcją w odniesieniu do this nie ma sposobu $watch.

Czy istnieje sposób na uzyskanie wartości $watch w formacie Controller As?

JS Fiddle

Odpowiedz

19

Nawet formacie controllerAs The $scope ma.

W rzeczywistości to, co robi controllerAs, wiąże instancję kontrolera z this z zakresem $.
E.g. controller="myController as myctrl" robi (za kulisami): $scope.myctrl = this (gdzie this odnosi się do instancji myController).

Tak, można po prostu wstrzyknąć i użyć $scope do zegarków:

.controller('myController', function ($scope, contacts) { 
    this.contacts = contacts; 

    $scope.$watch(function() { 
     return contacts; 
    }, function (newValue, oldValue) {...}); 
}); 
+1

Dzięki, @ExpertSystem, próbowałem wstrzykiwać '$ scope', ale próbowałem' $ scope. $ Watch (this.contacts, ... 'i nie zdawałem sobie sprawy z tego, że obserwowana wartość była zwracana w tym formacie. – Malkus

+0

Pomóż mi zrozumieć http://plnkr.co/edit/mFugWfzT2bLGVxwJyBfT?p=preview.Nie widzę żadnych alertów podczas zmiany wartości :( –

4
$scope.$watch("contact", callback, true) // true makes it a deep/recursive watch 
+1

Klucz jest trzecim parametrem: * true *, który stanowi głęboki zegarek.Próbowałem dużo, ale funkcja wywołania zwrotnego nie uruchomiła się ... –

1

Spróbuj tego,

$scope.$watch(angular.bind(this, function() { 
      return this.contacts; 
     }), function (newValue, oldValue) { 
      console.log((newValue + ' - ' + oldValue)); 
     }); 
+0

Witamy w Stack Overflow! Dodatkowe wyjaśnienia poprawiłoby twoją odpowiedź. – ryanyuyu

0

Inne napisane wyraźnie o tym, dlaczego jest generalnie nadal wymagane $ zakres. Ale nie w jaki sposób faktycznie oglądać swoje zmienne w przypadku twojego przykładu, aby odpowiednio obejrzeć lokalną zmienną "kontakty", musisz ją zidentyfikować według przestrzeni nazw kontrolera.

Więc:

$scope.$watch('myctrl.contacts', function(newValue, oldValue) { 
     console.log({older: oldValue, newer:newValue}); 
    }); 

Pomysł wykorzystania przestrzeni nazw lokalnych jest zapobieganie mutacji, jeśli tworzenie kontrolerów podrzędnych wewnątrz innego kontrolera. Zaletą tego jest to, że kontroler nadrzędny może oglądać wszystkie przestrzenie w jego zasięgu.

Powiedzmy, że początkowa html wyglądał mniej więcej tak:

<div ng-app="myApp" ng-controller="myController as myctrl"> 
    <div ng-controller="listController as mylist"> 
    <ul> 
     <li ng-repeat="contact in myctrl.contacts"> 
      <input type="text" ng-model="contact.name.first" /> 
     </li> 
    </ul> 
    </div> 
</div> 

i JS:

angular.module('myApp',[]) 
.controller('myController',['$scope',function(contacts) { 

    $scope.$watch('mylist.contacts', function(newValue, oldValue) { 
     console.log({older: oldValue, newer:newValue}); 
    }) 
.controller('listController',['contacts',function(contacts) { 
    this.contacts = contacts; 
    }); 
}]); 

Teraz główny sterownik obserwuje działalność w zagnieżdżonych kontroler ... bardzo ładne.