web-dev-qa-db-ja.com

Angularパラメーター変更時のディレクティブの更新

次のように初期化されるangularディレクティブがあります。

<conversation style="height:300px" type="convo" type-id="{{some_prop}}"></conversation>

$scope.some_propが変更されたときにディレクティブを更新するのに十分スマートであり、それは完全に異なるコンテンツを表示する必要があることを意味します。

私はそれをテストしましたが、何も起こりません。リンク関数は$scope.some_propが変更されても呼び出されません。これを実現する方法はありますか?

72
Luke Sapan

リンク関数は1回しか呼び出されないため、期待したことを直接行いません。モデル変数を監視するには、angular $watchを使用する必要があります。

この時計は、リンク機能で設定する必要があります。

ディレクティブに分離スコープを使用する場合、スコープは次のようになります

scope :{typeId:'@' }

リンク関数で、次のような時計を追加します

link: function(scope, element, attrs) {
    scope.$watch("typeId",function(newValue,oldValue) {
        //This gets called when data changes.
    });
 }

分離スコープを使用していない場合は、some_propでwatchを使用します

93
Chandermani

あなたがやろうとしているのは、ディレクティブ内の属性のプロパティを監視することです。次のように$ observe()を使用して、属性の変更のプロパティを監視できます。

angular.module('myApp').directive('conversation', function() {
  return {
    restrict: 'E',
    replace: true,
    compile: function(tElement, attr) {
      attr.$observe('typeId', function(data) {
            console.log("Updated data ", data);
      }, true);

    }
  };
});

モデルがあるかどうか、およびこれがパフォーマンスに影響を与えるかどうかについては言及していないため、ここでディレクティブで「コンパイル」関数を使用したことに注意してください。

モデルがある場合は、「compile」関数を「link」に変更するか、「controller 'およびモデルの変更のプロパティを監視するには、$ watch()を使用し、angular {{}}ブラケットを使用する必要がありますプロパティから、例:

<conversation style="height:300px" type="convo" type-id="some_prop"></conversation>

そしてディレクティブでは:

angular.module('myApp').directive('conversation', function() {
  return {
    scope: {
      typeId: '=',
    },
    link: function(scope, Elm, attr) {

      scope.$watch('typeId', function(newValue, oldValue) {
          if (newValue !== oldValue) {
            // You actions here
            console.log("I got the new value! ", newValue);
          }
      }, true);

    }
  };
});
38
j8io

これが親スコープの値のディレクティブの再読み込み/更新に役立つことを願っています

<html>

        <head>
            <!-- version 1.4.5 -->
            <script src="angular.js"></script>
        </head>

        <body ng-app="app" ng-controller="Ctrl">

            <my-test reload-on="update"></my-test><br>
            <button ng-click="update = update+1;">update {{update}}</button>
        </body>
        <script>
            var app = angular.module('app', [])
            app.controller('Ctrl', function($scope) {

                $scope.update = 0;
            });
            app.directive('myTest', function() {
                return {
                    restrict: 'AE',
                    scope: {
                        reloadOn: '='
                    },
                    controller: function($scope) {
                        $scope.$watch('reloadOn', function(newVal, oldVal) {
                            //  all directive code here
                            console.log("Reloaded successfully......" + $scope.reloadOn);
                        });
                    },
                    template: '<span>  {{reloadOn}} </span>'
                }
            });
        </script>


   </html>
1
Abdul
angular.module('app').directive('conversation', function() {
    return {
        restrict: 'E',
        link: function ($scope, $Elm, $attr) {
            $scope.$watch("some_prop", function (newValue, oldValue) {
                  var typeId = $attr.type-id;
                  // Your logic.
            });
        }
    };
}
0
Gelio

AngularJS 1.5.3以降の場合は、ディレクティブではなくコンポーネントに移行することを検討する必要があります。これらはディレクティブと非常に似ていますが、一方向のバインディングが更新されるたびに呼び出されるライフサイクルフックの1つである$ onChanges(changesObj)など、いくつかの非常に便利な追加機能を備えています。

app.component('conversation ', {
    bindings: {
    type: '@',
    typeId: '='
    },
    controller: function() {
        this.$onChanges = function(changes) {
            // check if your specific property has changed
            // that because $onChanges is fired whenever each property is changed from you parent ctrl
            if(!!changes.typeId){
                refreshYourComponent();
            }
        };
    },
    templateUrl: 'conversation .html'
});

コンポーネントを深く掘り下げるための docs を次に示します。

0
voodoo_patch