web-dev-qa-db-ja.com

データ変更時に$ watchが起動しない

私は、ui-select2ドロップダウンのモデル(ui-bootstrapから)に対して時計をセットアップしています。時計はロード時に起動しますが、データの変更では起動せず、その理由はわかりません。

モデルの変更を$ applyしなかったり、等値比較のために3番目のパラメーターを使用しない(通常、少なくともコードから)という通常の問題ではありません。

発射するにはどうすればいいですか?

問題を実証するプランクです

57
µBio

いくつか修正しました。

http://plnkr.co/edit/5Zaln7QT2gETVcGiMdoW?p=preview

JS

var myMod = angular.module("myApp",[]).controller("MainController",  function($scope){
  $scope.myModel = {selectedId:null};
}).controller("DetailController",function($scope){
  $scope.items = [1,2,3,4];

  $scope.watchHitCount = 0;
  $scope.$watch('myModel.selectedId', function(newVal, oldVal){
    console.log(newVal + " " + oldVal);
    $scope.watchHitCount++;
  },true);
});

Index.html

  <body ng-app="myApp">
    <div ng-controller="MainController">
      <ng-include src="'detail.html'" ng-controller="DetailController"></ng-include>
    </div>
  </body>

Detail.html

<pre>watch hit: {{watchHitCount}}</pre>
<pre>selected value: {{myModel.selectedId}}</pre>
<select ng-model="myModel.selectedId" ui-select2="">
  <option></option>
  <option ng-repeat="item in items" value="{{item}}">{{item}}</option>
</select>

コントローラが見つからないという不満があったので、名前付きのng-appと、コントローラが定義されていると宣言されたモジュールで通常行う方法でセットアップしました。

モデルに値を保持するオブジェクトも追加しました。$ scopeオブジェクトをモデルとして使用するのは悪い習慣です。代わりにスコープが参照する必要がありますモデルであるオブジェクトに。

35
shaunhusain

.$watch()の3番目の引数としてtrueを渡してみてください

$rootScope.Scopeドキュメント

$watch(watchExpression, listener, objectEquality)

objectEquality(optional)– {boolean =} –参照ではなく同等かどうかオブジェクトを比較します。

121
Casey Flynn

そのための単純な修正があります。単純な変数の代わりに複雑なオブジェクトでウォッチを使用します

たとえば(DON "T USE)

$scope.selectedType=1;//default
$scope.$watch(
            function () {
                return $scope.selectedType;
            },
            function (newValue, oldValue) {
                if (!angular.equals(oldValue, newValue)) {
                    $scope.DoWork();
                }
            },
            true);

しかし、以下を使用

$scope.selecteditem={selectedType:1};
$scope.$watch(
            function () {
                return $scope.selecteditem.selectedType;
            },
            function (newValue, oldValue) {
                if (!angular.equals(oldValue, newValue)) {
                    $scope.DoWork();
                }
            },
            true);

スコープ変数だけでなく、オブジェクト内にある2番目の例の「slectedTypes」に注意してください。これは、古いAngularバージョンでも機能します。

12
Tarek El-Mallah

Controller-asアプローチを使用している場合、いくつかの読み方は次のような構文を示唆する場合があります。

var myController = {
    myValue: 1
};
$scope.$watch('$ctrl.myValue', function () {
    ...
}, true);

代わりに、次のような関数でフィールドをラップするだけです。

var myController = {
    myValue: 1
};
$scope.$watch(function () {
    return myController.myValue;
}, function () {
    ...
}, true);
6
garryp