web-dev-qa-db-fra.com

Comment accéder au contrôleur de la directive parent en l'exigeant récursivement?

J'essaie d'atteindre le contrôleur d'une directive "boîte" parent récursivement:

<body ng-app="main">

<!-- no nesting: parent is the just body -->
<box></box>

<script type="text/javascript">
angular.module('main', [])
.directive('box', function() {
    return {
        restrict: 'E',
        controller: function() { },
        require: '?^box',  // find optional PARENT "box" directive
        link: function(scope, iElement, iAttrs, controller) {
            // controller should be undefined, as there is no parent box
            alert('Controller found: ' + (controller !== undefined));
        }
    };
});
</script>
</body>

Je m'attendrais à ce que la variable de contrôleur soit undefined dans la fonction de lien, mais j'obtiens le contrôleur de la directive box réelle.

Donc ma question est ... comment accéder au contrôleur PARENT dans un cas comme celui-ci:

<box>
    <box></box>
</box>

http://jsfiddle.net/gjv9g/1/

20
maX

OK, je l'ai trouvé ...

si vous voulez mettre la main sur le contrôleur d'un élément parent:

...
link: function(scope, iElement, iAttrs, controller) {
    // http://docs.angularjs.org/api/angular.element
    // jQuery/jqLite Extras:
    //
    // controller(name) - retrieves the controller of the current element or its parent.
    // By default retrieves controller associated with the ngController directive.
    // If name is provided as camelCase directive name, then the controller for this
    // directive will be retrieved (e.g. 'ngModel').
    var parentCtrl = iElement.parent().controller('box');
}
...

Cela renvoie soit le contrôleur de la directive parent, soit, un niveau plus haut, le contrôleur de la directive parent du parent.Si vous devez vous assurer d'obtenir un contrôleur d'un parent DIRECT, j'ai trouvé cela (peut-être qu'il existe une meilleure solution, je ne le fais pas savoir):

...
controller: function($scope, $element) {
    // store the element in controller, we'll need it later
    this.$element = $element;
},
// works in both pre and post link functions
link: function() {
    var parentElement = $element.parent();
    var parentCtrl = parentElement.controller('box');

    var hasDirectBoxParent = parentCtrl && parentCtrl.$element[0] === parentElement[0];

}
...

Exemple 1:

<box id="a">
    <box id="b"></box>
<box>

Lorsque la fonction de lien est invoquée sur la "case a", parentCtrl est undefined dans les deux cas. Lorsque la fonction de liaison est invoquée sur la "boîte b", parentCtrl est le contrôleur de la "boîte a" dans les deux cas.

Exemple 2:

<box id="a">
    <div>
        <box id="b"></box>
    </div>
<box>

Lorsque la fonction de lien est invoquée sur la "case a", parentCtrl est undefined dans les deux cas. Lorsque la fonction de liaison est invoquée sur la "boîte b", parentCtrl est toujours le contrôleur de la "boîte a" dans les deux cas, mais hasDirectBoxParent est false, vous pouvez donc distinguer le parent d'un grand-parent.

18
maX

Depuis Angular 1.3 vous pouvez utiliser deux accents ^^ pour rechercher une directive dans les éléments parents "uniquement".

Citation de la Angular Docs sur require :

  • (no prefix) - Localisez le contrôleur requis sur l'élément actuel. Lance une erreur s'il n'est pas trouvé.
  • ? - Essayez de localiser le contrôleur requis ou passez null au lien fn s'il n'est pas trouvé.
  • ^ - Localisez le contrôleur requis en recherchant l'élément et ses parents. Lance une erreur s'il n'est pas trouvé.
  • ^^ - Localisez le contrôleur requis en recherchant les parents de l'élément. Lance une erreur s'il n'est pas trouvé.
  • ?^ - Essayez de localiser le contrôleur requis en recherchant l'élément et ses parents ou passez null au lien fn s'il n'est pas trouvé.
  • ?^^ - Essayez de localiser le contrôleur requis en recherchant les parents de l'élément, ou passez null au lien fn s'il n'est pas trouvé.

Dans votre cas, remplacez require: '?^box', avec require: '?^^box',

39
Joel Kornbluh

require injecte le contrôleur de la directive requise (parent) dans la directive actuelle (à partir des documents angular: "require - Exige une autre directive et injecte son contrôleur comme quatrième argument) à la fonction de liaison " http://docs.angularjs.org/guide/directive )

Alors peut-être que vous obtenez déjà ce que vous voulez? Autrement dit, le contrôleur parent injecté aux enfants via votre paramètre controller.

4
KayakDave