0

Im obigen Beispiel, wenn ich das Wert-Array an die Direktive vom Controller übergeben, werden alle Änderungen in der Direktive html widergespiegelt. Ich meine, ich kann die Änderungen in der Benutzeroberfläche sehen.Angular Binding funktioniert nicht in benutzerdefinierten Direktive für lokalen Bereich Variablen mit übergebenen Daten berechnet

Aber Veränderungen im Wert von $scope.message Variable reflektiert nicht erhalten, auch wenn der Wert von $scope.message aus dem Wert von $scope.myData, deren Wert berechnet wird, ändert sich immer $timeout in der übergeordneten Steuerung mit , jene Änderungen zu sehen $scope.message, müssen Sie das Array mit $watchCollection überwachen. Meine Fragen sind,

  1. Warum eckige Bindung funktioniert nicht für $scope.myData normalerweise?
  2. Was sind andere "bekannte" Fälle, in denen die Bindung von Winkeln nicht funktioniert?

Unten ist der Code-Schnipsel

(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>' 
       } 
      }) 
})() 

Below html

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

Um oben genannten Richtlinie funktioniert, ich unten ändert

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

hier gemacht ist der Link zu plunkr.

plunker

Antwort

0

Ich würde dies nicht nennen "corner case" der Daten in Winkel binden.

Die Datenbindung von Angulars funktioniert, indem kontinuierlich die an $ scope angehängten Werte überprüft werden. Es ist cool, aber es ist keine Magie, in einer imperativen Sprache wie JavaScript-Anweisung $scope.message = condition ? "message": "another message"; wird nicht an sich vorschlagen, dass der Ausdruck jemals wieder neu bewertet werden würde. Angular initialisiert den Controller nur einmal pro Anhang zur Vorlage und genau so oft wird die Anweisung im obigen Beispiel ausgewertet. Einmal. Danach ist es nur noch eine andere $scope Variable, deren Wert entweder "Nachricht" oder "eine andere Nachricht" ist und so wird es bleiben, wenn wir es nicht selbst ändern.

Sie haben das Problem selbst identifiziert. Der Wert von $scope.message hängt von $scope.myData ab, aber ohne die $watchCollection gibt es nichts, um diese Verbindung auf dem neuesten Stand zu halten. $watchCollection, auf der anderen Seite, wird immer wieder die $scope.myData; und dann die $scope.message = ... Funktionen neu zu bewerten, weil das ist, was Winkel macht es zu tun.

Persönlich würde ich es jedoch mit einem Funktionsgetter tun, anstatt den Wert $scope zuzuordnen und manuell auf dem neuesten Stand zu halten. Das ist näher an dem, was Sie ursprünglich versucht haben zu tun.

.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>' 
    } 
}) 

Nachdem wir nun einen Funktionsaufruf statt einen einfachen Wert verwenden, den Ausdruck, der die Nachricht erzeugt wird neu bewertet immer und immer wieder, die Ansicht zu aktualisieren, wenn nötig.

+0

das ist eine wirklich gute Lösung.Es hilft auch, $ scope nicht zu verwenden. $ Watch/Collection. Eine Frage, in diesem Problem, warum eine Getter-Funktion immer ausgewertet wird, während Nachricht nicht? – csjoshi04

+0

Beide werden ausgewertet. Mit '$ scope.message' wird der Controller-Code einmal ausgeführt und' $ scope.message' wird "OOPS, keine Honda-Autos", denn wenn es läuft, gibt es keine hondas. Angular überprüft weiterhin, was der Wert von $ scope.message ist, aber es wird sich nicht ändern. Angular kann nicht auf Ihren Code '$ scope.message = ($ scope.myData.indexOf (" Honda ") ...' zugreifen oder diesen wiederverwenden ..... Dieser indexOf-Check wird einmal ausgeführt und dann ist es weg, nur das Ergebnis wird angezeigt " – noppa

+0

So funktionieren Anweisungen in vielen Programmiersprachen. Aber Funktionen sind anders. Der Code in ihnen kann und wird so oft wie wir wollen neu bewertet werden. Anders als mit der einfachen Nachricht." value, angular kann die Funktion immer wieder aufrufen und sie auffordern, den Wert neu zu bewerten – noppa