Angular-styleguide: Gute Vorgehensweise für den Zugriff auf Eigenschaften des übergeordneten Controllers

Erstellt am 28. Juli 2015  ·  13Kommentare  ·  Quelle: johnpapa/angular-styleguide

Was ist unter Verwendung der Syntax controllerAs eine gute Vorgehensweise, um auf einfache Eigenschaften eines übergeordneten Controllers zuzugreifen oder diese zu ändern? Bitte sehen Sie das Beispiel unten. Ich mag es nicht, über $scope.$parent.parent auf sie zuzugreifen. Wie geht ihr in ähnlichen Situationen vor, ohne einen Dienst für eine so triviale Logik zu erstellen?

<div ng-controller="Parent as parent">

  <div ng-if="parent.showMessage">
    Some simple message.
  </div>

  <div ng-controller="ChildOne as childOne"></div>

</div>
app.controller('Parent', function () {
    var self = this;
    self.showMessage = true;
});

app.controller('ChildOne', function ($scope) {
    var self = this;
    self.foo = 'bar';
    // Some simple logic.
    if (self.foo === 'bar') {
        $scope.$parent.parent.showMessage = false;
    }
});
question

Hilfreichster Kommentar

Verwendung eines stärker komponentenorientierten Ansatzes:

<html ng-app="myApp">
  <body>
    <div ng-controller="ParentCtrl as vm">
      <my-directive on-foo-eq-bar="vm.updateMessage(msg)"></my-directive>
    </div>

    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script>
      angular.module('myApp', [])
        .controller('ParentCtrl', function($window) {
          var vm = this;
          vm.updateMessage = function(msg) {
            $window.alert(msg);
          };
        })
        .directive('myDirective', function() {
          return {
            scope: {
              onFooEqBar:'&'
            },
            controllerAs:'vm',
            controller: function($scope) {
              var self = this;
              self.foo = 'bar';
              // Some simple logic.
              if (self.foo === 'bar') {
                $scope.onFooEqBar({msg: false});
              }
            }
          };
        });
    </script>
  </body>
</html>

Alle 13 Kommentare

Können Sie ein echtes Beispiel geben? Ich kann mir nur Situationen vorstellen, in denen die Eltern das Objekt, das die untergeordneten Controller verwenden / ändern, bereits kennen und das Sie den untergeordneten Controllern über das Daten-ng-Modell geben. In diesem Fall kann der übergeordnete Controller auf das Objekt zugreifen. Auf diese Weise müssen Ihre Controller weder einander noch den Umfang des anderen kennen.

Oder machst du etwas anderes als ich denke?

@dietergeerts danke für deine Eingabe. In Ihrem Beispiel hat die Übergabe eines primitiven Werts an ein untergeordnetes Element mithilfe des ng-Modells keine Auswirkungen, wenn das untergeordnete Element diesen Wert ändert.

Grundsätzlich muss ich die erste Div zeigen, wenn eine einfache Logik für das Kind zutrifft.

(ChildOne ist an eine Route angehängt, daher kann ich nicht einfach die erste Div in das Kind stecken.)

@Bekt , es kann diesen Effekt haben, da data-ng-if = "parent.object.property == 'some_value'" sein könnte, natürlich abhängig davon, was die Logik ist und wie kompliziert diese Logik sein muss.

Wenn sie mit dem UI-Router über Routen festgelegt werden und untergeordnete Routen sind, können beide das Objekt verwenden.

Im Allgemeinen ist es eine sehr schlechte Idee, die Eltern um etwas bitten zu müssen, da dies bedeutet, dass der Controller nicht in sich geschlossen ist, was sie sein müssen. Normalerweise gibt es einen weitaus besseren Weg, um eine solche „Kommunikation“ durchzuführen. Deshalb habe ich nach der tatsächlichen Situation gefragt, die Sie haben, da es bessere Möglichkeiten geben könnte, das zu tun, was Sie wollen.

Ich mag es, Dinge entkoppelt zu halten. ABER es gibt nur wenige Absolute ... im Allgemeinen meine Anweisungen, meine Controller, meine Dienste ... Ich mag es, wenn sie in sich geschlossen sind und wenn sie externe Aspekte benötigen, injiziere ich sie oder binde sie. Ich mag es nicht, mich auf etwas zu verlassen, das in einem bestimmten Kontext verwendet wird. Sinn ergeben?

Ich würde dieses Problem lösen, indem ich eine Anweisung verwende, um den untergeordneten Controller wie folgt zu kapseln:

<div ng-controller="Parent as parent">

  <div ng-if="parent.showMessage">
    Some simple message.
  </div>

  <div child-one parent="parent"></div>

</div>
app.controller('Parent', function () {
    var self = this;
    self.showMessage = true;
});

app.directive('childOne', function() {
    return {
        controllerAs: 'childOne',
        controller: function($scope, $attrs) {
            var parent = $scope.$eval($attrs.parent);

            var self = this;
            self.foo = 'bar';
            // Some simple logic.
            if (self.foo === 'bar') {
                parent.showMessage = false;
            }
        }
    };
});

Oder um ein ng-init für den zweiten Controller zu verwenden.

<div ng-controller="ChildOne as childOne" ng-init="childOne.setParent(parent)"></div>

Verwendung eines stärker komponentenorientierten Ansatzes:

<html ng-app="myApp">
  <body>
    <div ng-controller="ParentCtrl as vm">
      <my-directive on-foo-eq-bar="vm.updateMessage(msg)"></my-directive>
    </div>

    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script>
      angular.module('myApp', [])
        .controller('ParentCtrl', function($window) {
          var vm = this;
          vm.updateMessage = function(msg) {
            $window.alert(msg);
          };
        })
        .directive('myDirective', function() {
          return {
            scope: {
              onFooEqBar:'&'
            },
            controllerAs:'vm',
            controller: function($scope) {
              var self = this;
              self.foo = 'bar';
              // Some simple logic.
              if (self.foo === 'bar') {
                $scope.onFooEqBar({msg: false});
              }
            }
          };
        });
    </script>
  </body>
</html>

@dbabaioff @leandrocosta : danke, interessante vorschläge.

Am Ende hatte ich $on für die Eltern und $broadcast für die Kinder.

Gute Unterhaltung, aber nichts, was man hier zum Leitfaden hinzufügen könnte, IMO

: +1:

Abonnieren Sie in Ihrem übergeordneten Controller ein Ereignis auf $ rootScope

$rootScope.$on('myEvent', function(data){/*do something*/})

Feuern Sie dann im untergeordneten Element das Ereignis mit $ rootScope ab

$rootScope.$emit('myEvent', someData);

Imho, es ist weitaus besser, zwei Komponenten anstelle von Controllern zu haben und bei Bedarf Eigenschaften in die untergeordnete Komponente einzufügen. Wenn Sie sie festlegen möchten, geben Sie etwas vom untergeordneten Element an das übergeordnete Element aus. Weitaus performanter und leichter zu überlegen + einfacher zu testen.

Die Verwendung von $ rootScope und Eventing wird heutzutage nicht mehr durchgeführt.

Sie können überprüfen, ob die Eigenschaft vorhanden ist, und dann den Wert wie unten gezeigt zuweisen.

if ($ scope. $ parent.showMessage) {
var parent = $ scope. $ parent;
while (! parent.hasOwnProperty ('showMessage')) {
parent = parent ['$ parent'];
}}
parent.showMessage = false;
}}

Es tut mir leid, dies zu nekrotisieren, aber für den Fall, dass jemand anderes hier landet, besteht meine Lösung darin, den untergeordneten Controller direkt in eine Komponente zu konvertieren und dann eine Aktualisierungsfunktion vom übergeordneten zum untergeordneten Element wie folgt zu binden:

<div ng-controller="Parent as parent">

  <div ng-if="parent.showMessage">
    Some simple message.
  </div>

  <child-one update-parent="parent.showMessage = value"></child-one>

</div>
app.controller('Parent', function () {
    var self = this;
    self.showMessage = true;
});

app.component('childOne', /* component def stuff including updateParent: '&' in bindings */);

function childOneController() {
    var self = this;
    self.foo = 'bar';
    // Some simple logic.
    if (self.foo === 'bar') {
        self.updateParent({value: false});
    }
});
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

jusefb picture jusefb  ·  9Kommentare

jansepke picture jansepke  ·  12Kommentare

samithaf picture samithaf  ·  12Kommentare

sgbeal picture sgbeal  ·  7Kommentare

amiceli picture amiceli  ·  7Kommentare