0

上記の例では、コントローラからのディレクティブに渡された値配列を変更すると、すべての変更がディレクティブhtmlに反映されます。つまり、UIの変更を見ることができます。渡されたデータを使用して計算されたローカルスコープ変数のカスタムディレクティブで角度バインディングが機能していない

しかし$scope.message変数の値の変化は$scope.messageの値がでこれらの変更を確認するには、親コントローラ に$timeoutを使用して、値が変化しつつある$scope.myDataの値から計算されていても、反映されません。 $scope.messageの場合、$watchCollectionを使用して配列を監視する必要があります。私の質問は、

  1. $scope.myDataでは正常に動作しないのはなぜですか?
  2. angleのバインディングが機能しない他の「既知の」コーナーケースは何ですか?以下は

以下のコードである

(function(){ 
    angular.module("csjoshi04.2waybinding",[]) 
      .controller("ParentCtrl",["$scope", "$timeout", function($scope, $timeout){ 
       $scope.myCars = ["Ford", "BMW", "Toyata"]; 
       $timeout(function(){ 
        $scope.myCars.push("Honda"); 
       }, 3000); 
      }]) 
      .directive("showMyData",function(){ 
       return { 
        restrict: "E", 
        scope: { 
         myData : "=" 
        }, 
        controller : ["$scope", function($scope){ 
         $scope.message = ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
        }], 
        template : '<div>{{message}}</div><ul ng-repeat="data in myData"><li>{{data}}</li></ul>' 
       } 
      }) 
})() 

ディレクティブの仕事の上に作るためにHTML

<body ng-controller="ParentCtrl"><show-my-data my-data="myCars" ></show-my-data></body> 

ですが、私は以下の作っここ

directive("showMyData",function(){ 
       return { 
        restrict: "E", 
        scope: { 
         myData : "=" 
        }, 
        controller : ["$scope", function($scope){ 
         $scope.message = ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
         $scope.$watchCollection(function(){ 
          return $scope.myData; 
         }, function(new1, old){ 
          $scope.message = ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
         }); 
        }], 
        template : '<div>{{message}}</div><ul ng-repeat="data in myData"><li>{{data}}</li></ul>' 
       } 
      }) 

を変更へのリンクですplunkr。

plunker

答えて

0

私はこの「コーナーケース」の角度でデータバインディングの呼び出すことはありません。

Angularのデータバインディングは、$ scopeに添付された値を継続的にチェックすることによって機能します。それはクールですが、JavaScriptステートメント $scope.message = condition ? "message": "another message";のような命令的言語では、表現が再び再評価されることを示唆するものではありません。 Angularは、テンプレートへの添付ファイルごとにコントローラを1回だけ初期化します。これは、上記の例のステートメントが評価される正確な回数です。 1回。その後、値が "メッセージ"または "別のメッセージ"である別の$scope変数があります。それは、私たち自身を変更しなければ、それがどのように残るかです。

あなた自身で問題を特定しました。 $scope.messageの値は$scope.myDataに依存しますが、$watchCollectionがないと、このリンクを最新の状態に保つことはできません。一方、$watchCollectionは、最初に$scope.myData;、次に$scope.message = ...の機能を再評価し続けるでしょう。なぜなら、それが角度を変えるためです。

個人的には、値を$scopeに割り当てずに、手動で最新の状態に保つ代わりに、関数ゲッターを使用します。とにかく元々はやろうとしていたことに近いです。

.directive("showMyData",function(){ 
    return { 
     restrict: "E", 
     scope: { 
      myData : "=" 
     }, 
     controller : ["$scope", function($scope){ 
      $scope.getMessage = function(){ 
       return ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
      };  
     }], 
     template : '<div>{{getMessage()}}</div><ul ng-repeat="data in myData"><li>{{data}}</li></ul>' 
    } 
}) 

今、私たちが代わりに単純な値の関数呼び出しを使用している、メッセージを作成する式は、何度も何度も再評価されることを、必要に応じてビューを更新します。

+0

これは本当に良い解決策です。また、$ scope/$ collectionを使用しない場合に役立ちます。しかし、この問題でゲッター関数が評価されるのに対し、メッセージが得られないのはなぜですか? – csjoshi04

+0

両方とも評価されます。 '$ scope.message'ではコントローラコードが一度実行され、' $ scope.message'は "OOPS、honda cars"になります。なぜなら、実行されるとホンダは存在しないからです。 Angularは '$ scope.message'の値が何であるかをチェックし続けますが、変更されません。 Angularはあなたのコード '$ scope.message =($ scope.myData.indexOf(" Honda ")...'。。 にアクセスまたは再利用することはできません。そのindexOfチェックは一度実行され、 – noppa

+0

これは、多くのプログラミング言語で文がどのように機能するのかということですが、関数は異なります。それらの中のコードは、必要な回数だけ再評価することができます。値は、角度は、値を再評価するように求める機能を繰り返し呼び出すことができます – noppa

関連する問題