it-swarm.com.de

AngularJS-Direktive-Controller, die übergeordnete Direct-Controller benötigen?

Ich denke vielleicht ganz rückwärts darüber nach, aber ich versuche drei verschachtelte Direktiven zu machen, nennen wir sie: Bildschirm, Komponente und Widget. Ich möchte, dass das Widget in der Lage ist, ein bestimmtes Verhalten in einer Komponente auszulösen, was wiederum ein gewisses Verhalten im Bildschirm auslöst. So:

.directive('screen', function() {
    return {
        scope: true,
        controller: function() {
            this.doSomethingScreeny = function() {
                alert("screeny!");
            }
        }
    }
})

.directive('component', function() {
    return {
        scope: true,
        controller: function() {
            this.componentFunction = function() {
                WHAT.doSomethingScreeny();
            }
        }
    }
})

.directive('widget', function() {
    return {
        scope: true,
        require: "^component",
        link: function(scope, element, attrs, componentCtrl) {
            scope.widgetIt = function() {
                componentCtrl.componentFunction();
            };
        }
    }
})

<div screen>
    <div component>
        <div widget>
            <button ng-click="widgetIt()">Woo Hoo</button>
        </div>
    </div>
</div>

Ich kann übergeordnete Komponenten im Link fn eines Widgets mit require: "^component" verwenden. Wie kann ich Komponentencontroller außerdem Zugriff auf den zugehörigen Bildschirm gewähren? 

Was ich brauche, ist das WAS in der Komponente. Wenn Sie auf die Schaltfläche des Widget klicken, wird "screeny!".

Vielen Dank.

30
nicholas

Es gibt zwei Möglichkeiten, wie Sie Ihr Problem lösen können:

  1. Da Sie scope: true verwenden, erben alle Bereiche prototypisch. Wenn Sie also Ihre Methoden für $scope statt für this im Controller screen definieren, haben sowohl component als auch widget Zugriff auf die Funktion doSomethingScreeny.
    Fiddle .
  2. Definieren Sie eine Link-Funktion für component und require: '^screen'. Speichern Sie in der Link-Funktion die screenCtrl in einer Bereichseigenschaft. Anschließend können Sie im Controller der Direktive darauf zugreifen (inject $scope) .
    Fiddle .
35
Mark Rajcok

Die meisten dieser Dinge schlagen fehl, wenn Sie beim Erstellen des Controllers direkt auf die Eigenschaften oder Methoden des übergeordneten Controllers zugreifen möchten. Ich habe eine andere Lösung gefunden, indem ich Abhängigkeitsinjektion und den $controller-Dienst verwendete.

.directive('screen', function ($controller) {
    return {
       require: '^parent',
       scope: {},
       link: function (scope, element, attr, controller) {
           $controller('MyCtrl', {
                $scope: scope,
                $element: element,
                $attr, attr, 
                controller: controller
           });
       }
    }
})

.controller('MyCtrl, function ($scope, $element, $attr, controller) {});

Diese Methode ist besser prüfbar und belastet Ihren Bereich nicht mit unerwünschten Controllern.

5
malte

var myApp = angular.module('myApp', [])

.directive('screen', function() {
  return {
    scope: true,
    controller: function() {
      this.doSomethingScreeny = function() {
        alert("screeny!");
      }
    }
  }
})

.directive('component', function() {
  return {
    scope: true,
    controller: function($element) {
      this.componentFunction = function() {
        $element.controller('screen').doSomethingScreeny();
      }
    }
  }
})

.directive('widget', function() {
  return {
    scope: true,
    controller: function($scope, $element) {
      $scope.widgetFunction = function() {
        $element.controller('component').componentFunction();
      }
    }
  }
})

.controller('MyCtrl', function($scope) {
  $scope.name = 'Superhero';
})
<body ng-app="myApp">

  <div ng-controller="MyCtrl">
    <div screen>
      <div component>
        <div widget>
          <button ng-click="widgetFunction()">Woo Hoo</button>
        </div>
      </div>
    </div>
  </div>

</body>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>

Wenn Sie auf eine in screen - Direktive-Controller definierte Funktion von component - Direktive-Controller (keine Link-Funktion) zugreifen möchten, können Sie $element.controller('screen').doSomethingScreeny() (von component - Direktive) verwenden.

JSFiddle

Winkel Dokumentation :

  • controller(name) - ruft den Controller des aktuellen Elements oder .__ ab. sein Elternteil. Ruft standardmäßig den Controller ab, der dem .__ zugeordnet ist. ngController Direktive. Wenn name als camelCase-Direktive angegeben ist name, dann wird der Controller für diese Direktive abgerufen (z. B. . 'ngModel').
0
Felix

return {scope: true} oder return {scope: false} wirkt sich nicht auf die Variable $ scope in controller: function ($ scope) {} in jeder Anweisung aus, aber das Direktive-Tag muss in den Tag ng-controller oder ng-app eingefügt werden .

JSFiddle

JSFiddle

0