web-dev-qa-db-ja.com

Angularjsは親スコープの変更を監視します

私はディレクティブを書いていますが、親スコープの変更を監視する必要があります。私がこれを好ましい方法で行っているかどうかはわかりませんが、次のコードでは動作しません:

  scope.$watch(scope.$parent.data.overlaytype,function() {
    console.log("Change Detected...");
  })

これはウィンドウのロード時に記録されましたが、overlaytypeが変更された場合でも、二度と記録されませんでした。

overlaytypeの変更を確認するにはどうすればよいですか?

編集:ここに指令全体があります。なぜ子スコープを取得するのか完全にはわかりません

/* Center overlays vertically directive */
aw.directive('center',function($window){
  return {
    restrict : "A",
    link : function(scope,elem,attrs){

      var resize = function() {
        var winHeight = $window.innerHeight - 90,
            overlayHeight = elem[0].offsetHeight,
            diff = (winHeight - overlayHeight) / 2;
            elem.css('top',diff+"px");
      };

      var watchForChange = function() {
        return scope.$parent.data.overlaytype;
      }
      scope.$watch(watchForChange,function() {
        $window.setTimeout(function() {
          resize();
        }, 1);
      })

      angular.element($window).bind('resize',function(e){
        console.log(scope.$parent.data.overlaytype)
        resize();
      });
    }
  };
});
43
wesbos

子スコープにはdataプロパティが必要です。スコープは親スコープと子スコープの間でプロトタイプ継承を使用します。

また、$ watchメソッドが予期する最初の引数は、変数からの値ではなく、評価する式または関数です。そのため、代わりに送信する必要があります。

7
Naor Biton

親スコープのプロパティを監視する場合は、親スコープの$watchメソッドを使用できます。

//intead of $scope.$watch(...)
$scope.$parent.$watch('property', function(value){/* ... */});

EDIT 2016:上記は正常に機能するはずですが、実際にはクリーンなデザインではありません。代わりに directive または component を使用し、その依存関係をバインディングとして宣言してください。これにより、パフォーマンスが向上し、デザインがよりきれいになります。

73
Petr Peller

コントローラー間で$ broadcastを使用してこれを実行することをお勧めします。これは、親/子コントローラー間の通信のangular方法のようです

コンセプトはシンプルです。親コントローラーで値を監視し、変更が発生したら、それをブロードキャストして子コントローラーでキャッチできます。

これを示すフィドルは次のとおりです。 http://jsfiddle.net/DotDotDot/f733J/

親コントローラーのパーツは次のようになります。

$scope.$watch('overlaytype', function(newVal, oldVal){
    if(newVal!=oldVal)
        $scope.$broadcast('overlaychange',{"val":newVal})
});

そして子コントローラーで:

$scope.$on('overlaychange', function(event, args){
    console.log("change detected")
    //any other action can be perfomed here
});

このソリューションの良い点は、別の子コントローラーで変更を監視したい場合、同じイベントをキャッチするだけです

楽しんで

編集:最後の編集は表示されませんでしたが、私のソリューションはディレクティブでも機能し、前のフィドルを更新しました( http://jsfiddle.net/DotDotDot/f733J/1/

子スコープを作成してコントローラーを作成するようにディレクティブを変更しました:

directive('center',function($window){
  return {
    restrict : "A",
    scope:true,
    controller:function($scope){
        $scope.overlayChanged={"isChanged":"No","value":""};
        $scope.$on('overlaychange', function(event, args){
        console.log("change detected")
        //whatever you need to do

    });
  },
link : function(scope,elem,attrs){

  var resize = function() {
    var winHeight = $window.innerHeight - 90,
        overlayHeight = elem[0].offsetHeight,
        diff = (winHeight - overlayHeight) / 2;
        elem.css('top',diff+"px");
  };
  angular.element($window).bind('resize',function(e){
    console.log(scope.$parent.data.overlaytype)
    resize();
      });
    }
  };
});
22
DotDotDot

子スコープ内の親スコープ変数を監視する場合は、$watchの2番目の引数としてtrueを追加できます。これにより、オブジェクトが変更されるたびにウォッチがトリガーされます

$scope.$watch("searchContext", function (ctx) {
                ...
            }, true);
6
S. Ktifa

申し分なく、ここに私の2セントがありますが、イベントオプションも好きです:

更新されたフィドルhttp://jsfiddle.net/enU5S/1/

HTML

<div ng-app="myApp" ng-controller="MyCtrl">
    <input type="text" model="model.someProperty"/>
    <div awesome-sauce some-data="model.someProperty"></div>
</div>

JS

angular.module("myApp", []).directive('awesomeSauce',function($window){
  return {
    restrict : "A",
      template: "<div>Ch-ch-ch-changes: {{count}} {{someData}}</div>",
      scope: {someData:"="},
      link : function(scope,elem,attrs){
        scope.count=0;
        scope.$watch("someData",function() {
            scope.count++;
        })
    }
  };
}).controller("MyCtrl", function($scope){
    $scope.model = {someProperty: "something here");
});

ここで示しているのは、子と親からの双方向バインディングを持つ変数を持つことができますが、子がプロパティを取得するために親に到達する必要はないということです。ディレクティブの上に新しい親を追加すると、物事に手を伸ばす傾向がおかしくなります。

ボックスに入力すると、コントローラーのモデルが更新されます。これは、ディレクティブのプロパティにバインドされるため、ディレクティブで更新されます。ディレクティブリンク関数内には監視設定があり、スコープ変数が変更されるたびにカウンターが増分されます。

分離スコープの詳細と、= @または&の使用の違いについては、こちらをご覧ください。 http://www.egghead.io/

2
shaunhusain