Используйте `this. $Watch` вместо` $scope. $Watch` с 'Controller As'

В настоящее время я использую формат Controller As для контрольных контроллеров.

Это отлично работает для того, чтобы держать объем значений на представлениях понятным и легким для подражания.

<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>

Однако при реализации $watch я сталкиваюсь с проблемами, поскольку он, похоже, зависит от $scope, поэтому следующее не будет работать.

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

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

}]);

Я получаю undefined не функция в отношении this, не имеющая метода $watch.

Есть ли способ $watch значения в формате Controller As?

JS Fiddle

Ответ 1

Даже в формате controllerAs существует $scope.

Фактически, то, что controllerAs делает, связывает экземпляр контроллера this с областью $.
Например. controller="myController as myctrl" (за кадром): $scope.myctrl = this (где this относится к экземпляру myController).

Итак, вы можете просто вводить и использовать $scope для часов:

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

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

Ответ 2

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

Ответ 3

Попробуйте это,

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

Ответ 4

Другие четко пишут, почему, как правило, требуется область $. Но не так, как фактически наблюдать за вашими переменными в случае вашего примера, чтобы правильно наблюдать локальную переменную "контакты", вы должны идентифицировать ее по пространству имен контроллера.

Итак:

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

Идея использования локального пространства имен заключается в предотвращении мутации, если вы создаете дочерние контроллеры внутри другого контроллера. Хорошим преимуществом этого является то, что родительский контроллер может просматривать все пробелы внутри своей области.

Давайте скажем, что начальный html выглядел примерно так:

<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>

и 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;
    });
}]);

Теперь главный контроллер отслеживает активность во вложенном контроллере... довольно изящный.