Aktualisierung der Winkelrichtlinie bei Parameteränderung

75

Ich habe eine Winkelanweisung, die wie folgt initialisiert ist:

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

Ich möchte, dass es intelligent genug ist, um die Direktive bei $scope.some_propÄnderungen zu aktualisieren , da dies impliziert, dass völlig andere Inhalte angezeigt werden sollten.

Ich habe es so getestet wie es ist und nichts passiert, die Verknüpfungsfunktion wird nicht einmal aufgerufen, wenn $scope.some_propÄnderungen vorgenommen werden. Gibt es eine Möglichkeit, dies zu erreichen?

Luke Sapan
quelle

Antworten:

97

Die Link-Funktion wird nur einmal aufgerufen, sodass sie nicht direkt das tut, was Sie erwarten. Sie müssen eckig verwenden $watch, um eine Modellvariable zu überwachen.

Diese Uhr muss in der Link-Funktion eingerichtet werden.

Wenn Sie einen isolierten Bereich für die Direktive verwenden, lautet der Bereich

scope :{typeId:'@' }

In Ihrer Link-Funktion fügen Sie dann eine Uhr wie hinzu

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

Wenn Sie keinen isolierten Bereich verwenden, verwenden Sie watch on some_prop

Chandermani
quelle
7
Ich arbeite an einem ähnlichen Problem wie das OP. Die AngularJS-Dokumente implizieren, dass die Verwendung von =in scope:eine bidirektionale Bindung erstellt, dh Änderungen im untergeordneten Bereich werden auf den übergeordneten Bereich übertragen und umgekehrt - ist dies nicht der Fall? Ich muss in der Lage sein, eine Anweisung anzuweisen, sich selbst vom übergeordneten Controller zu aktualisieren.
Eno
@Eno Hast du das herausgefunden? Wirklich verwirrend mich!
JMK
Ist es schädlich, wenn mehr als 10000 Direktiven einen Gültigkeitsbereich starten. $ Watch, um auf einen Bool zum Aktualisieren zu warten?
Léon Pelletier
Ich habe festgestellt, dass die obige Lösung nicht funktioniert, wenn der Parameter '=' verwendet, und ich untersuche sie.
Micky
38

Sie versuchen, die Eigenschaft des Attributs in der Direktive zu überwachen. Sie können die Eigenschaft von Attributänderungen mit $ watch () wie folgt beobachten:

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);

    }
  };
});

Denken Sie daran, dass ich hier in der Direktive die Funktion 'Kompilieren' verwendet habe, da Sie nicht erwähnt haben, ob Sie Modelle haben und ob dies leistungsabhängig ist.

Wenn Sie Modelle haben, müssen Sie die Funktion ' Kompilieren ' in ' Verknüpfen ' ändern oder ' Controller ' verwenden und die Eigenschaft von Modelländerungen überwachen. Verwenden Sie $ watch () und nehmen Sie den Winkel {{}} Klammern aus der Eigenschaft, Beispiel:

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

Und in der Richtlinie:

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);

    }
  };
});
j8io
quelle
1

Ich hoffe, dies wird dazu beitragen, die Direktive zum Wert aus dem übergeordneten Bereich neu zu laden / zu aktualisieren

<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>
Abdul
quelle
0
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.
            });
        }
    };
}
Gelio
quelle
0

Wenn Sie unter AngularJS 1.5.3 oder neuer arbeiten, sollten Sie in Betracht ziehen, anstelle von Anweisungen zu Komponenten zu wechseln. Diese funktionieren sehr ähnlich wie Direktiven, enthalten jedoch einige sehr nützliche zusätzliche Funktionen, wie z. B. $ onChanges (ChangesObj), einen der Lifecycle-Hooks, der aufgerufen wird, wenn Einwegbindungen aktualisiert werden.

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

Hier sind die Dokumente zum Vertiefen in Komponenten.

voodoo_patch
quelle