web-dev-qa-db-fra.com

Angularjs: 'controller as syntax' et $ watch

Comment s'abonner lorsque la propriété change en utilisant la syntaxe controller as?

controller('TestCtrl', function ($scope) {
  this.name = 'Max';
  this.changeName = function () {
    this.name = new Date();
  }
  // not working       
  $scope.$watch("name",function(value){
    console.log(value)
  });
});
<div ng-controller="TestCtrl as test">
  <input type="text" ng-model="test.name" />
  <a ng-click="test.changeName()" href="#">Change Name</a>
</div>  
152
Miron

Il suffit de lier le contexte pertinent.

$scope.$watch(angular.bind(this, function () {
  return this.name;
}), function (newVal) {
  console.log('Name changed to ' + newVal);
});

Exemple: http://jsbin.com/yinadoce/1/edit

UPDATE:

La réponse de Bogdan Gersak est en fait une sorte d'équivalent, les deux réponses tentent de lier this avec le bon contexte. Cependant, j'ai trouvé sa réponse plus propre.

Cela dit, vous devez avant tout comprendre l'idée sous-jacente qui la sous-tend .

UPDATE 2:

Pour ceux qui utilisent ES6, en utilisant arrow function, vous obtenez une fonction avec le bon contexte OOTB.

$scope.$watch(() => this.name, function (newVal) {
  console.log('Name changed to ' + newVal);
});

Exemple

158
Roy Miloh

Je fais habituellement ceci:

controller('TestCtrl', function ($scope) {
    var self = this;

    this.name = 'Max';
    this.changeName = function () {
        this.name = new Date();
   }

   $scope.$watch(function () {
       return self.name;
   },function(value){
        console.log(value)
   });
});
138
Bogdan Gersak

Vous pouvez utiliser:

   $scope.$watch("test.name",function(value){
        console.log(value)
   });

Cela fonctionne JSFiddle avec votre exemple.

23
Artyom Pranovich

Semblable à utiliser le "test" de "TestCtrl en tant que test", comme décrit dans une autre réponse, vous pouvez attribuer "self" à votre portée:

controller('TestCtrl', function($scope){
    var self = this;
    $scope.self = self;

    self.name = 'max';
    self.changeName = function(){
            self.name = new Date();
        }

    $scope.$watch("self.name",function(value){
            console.log(value)
        });
})

De cette manière, vous n'êtes pas lié au nom spécifié dans le DOM ("TestCtrl as test") et vous évitez également le besoin de .bind (this) à une fonction.

... à utiliser avec le code HTML d'origine spécifié:

<div ng-controller="TestCtrl as test">
    <input type="text" ng-model="test.name" />
    <a ng-click="test.changeName()" href="#">Change Name</a>
</div>
13
user4389

AngularJs 1.5 supporte le $ ctrl par défaut pour la structure ControllerAs.

$scope.$watch("$ctrl.name", (value) => {
    console.log(value)
});
11
Niels Steenbeek

Vous pouvez utiliser $ onChanges angular cycle de vie du composant.

voir la documentation ici: https://docs.angularjs.org/guide/component dans la section Application à base de composants

1
Pavel Durov

vous pouvez réellement passer une fonction en tant que premier argument de $ watch ():

 app.controller('TestCtrl', function ($scope) {
 this.name = 'Max';

// hmmm, a function
 $scope.$watch(function () {}, function (value){ console.log(value) });
 });

Ce qui signifie que nous pouvons retourner notre référence this.name:

app.controller('TestCtrl', function ($scope) {
    this.name = 'Max';

    // boom
    $scope.$watch(angular.bind(this, function () {
    return this.name; // `this` IS the `this` above!!
    }), function (value) {
      console.log(value);
    });
});

Lisez un article intéressant sur le sujet controllerAs https://toddmotto.com/digging-into-angulars-controller-as-syntax/

1
Alexandr

Écrire une montre $ watch en syntaxe ES6 n’a pas été aussi facile que prévu. Voici ce que vous pouvez faire:

// Assuming
// controllerAs: "ctrl"
// or
// ng-controller="MyCtrl as ctrl"
export class MyCtrl {
  constructor ($scope) {
    'ngInject';
    this.foo = 10;
    // Option 1
    $scope.$watch('ctrl.foo', this.watchChanges());
    // Option 2
    $scope.$watch(() => this.foo, this.watchChanges());
  }

  watchChanges() {
    return (newValue, oldValue) => {
      console.log('new', newValue);
    }
  }
}
0
Maciej Gurban