web-dev-qa-db-ja.com

Angularjs:「構文としてのコントローラー」と$ watch

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

関連するコンテキストをバインドするだけです。

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

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

UPDATE:

Bogdan Gersakの答えは実際には同等であり、両方の答えがthisを正しいコンテキストにバインドしようとします。しかし、私は彼の答えがきれいだとわかりました。

そうは言っても、何よりもまず、 その背後にある考え方 を理解する必要があります。

更新2:

ES6を使用している場合は、arrow functionを使用することで、正しいコンテキストOOTBの関数を取得できます。

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

158
Roy Miloh

私は通常これを行います:

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

次を使用できます。

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

これは動作しています JSFiddle あなたの例で。

23

別の答えで説明されているように、「TestCtrl as test」の「test」を使用するのと同様に、スコープに「self」を割り当てることができます。

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

この方法では、DOMで指定された名前(「テストとしてのTestCtrl」)に縛られず、関数に.bind(this)する必要もありません。

...指定された元のhtmlで使用する場合:

<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は、ControllerAs構造のデフォルトの$ ctrlをサポートしています。

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

$ onChangesangularコンポーネントのライフサイクルを使用できます。

こちらのドキュメントを参照してください: https://docs.angularjs.org/guide/component underコンポーネントベースのアプリケーションセクション

1
Pavel Durov

実際に関数を$ watch()の最初の引数として渡すことができます:

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

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

つまり、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);
    });
});

ControllerAsトピックに関する興味深い投稿を読む https://toddmotto.com/digging-into-angulars-controller-as-syntax/

1
Alexandr

ES6構文で$ watchを書くのは、思ったほど簡単ではありませんでした。できることは次のとおりです。

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