333 votes

Comment accéder à la portée parent à partir d'une directive personnalisée * avec sa propre portée * dans AngularJS?

Je suis à la recherche d'une quelconque façon de l'accès au "parent" portée à l'intérieur d'une directive. Toute combinaison de portée, transclude, exiger, en passant dans des variables (ou le champ d'application elle-même) à partir de ci-dessus, etc. Je suis totalement prêt à se plier en quatre, mais je veux éviter de quelque chose de totalement hacky ou difficile à maintenir. Par exemple, je sais que je pourrais le faire dès maintenant en prenant l' $scope de la preLink paramètres et d'itération sur ses $sibling des étendues de trouver les concepts de "parent".

Ce que je veux vraiment, c'est être en mesure d' $watch d'une expression dans la portée parent. Si je peux le faire, alors je peux accomplir ce que je suis en train de faire ici: AngularJS - Comment rendre une partielle avec les variables?

Une remarque importante est que la directive doit être ré-utilisable au sein de la même portée parent. Par conséquent, le comportement par défaut (champ d'application: false) ne fonctionne pas pour moi. J'ai besoin d'une portée individuelle par exemple de la directive, et puis j'ai besoin d' $watch une variable qui vit dans la portée parent.

Un exemple de code vaut 1000 mots, alors:

app.directive('watchingMyParentScope', function() {
    return {
        require: /* ? */,
        scope: /* ? */,
        transclude: /* ? */,
        controller: /* ? */,
        compile: function(el,attr,trans) {
            // Can I get the $parent from the transclusion function somehow?
            return {
                pre: function($s, $e, $a, parentControl) {
                    // Can I get the $parent from the parent controller?
                    // By setting this.$scope = $scope from within that controller?

                    // Can I get the $parent from the current $scope?

                    // Can I pass the $parent scope in as an attribute and define
                    // it as part of this directive's scope definition?

                    // What don't I understand about how directives work and
                    // how their scope is related to their parent?
                },
                post: function($s, $e, $a, parentControl) {
                    // Has my situation improved by the time the postLink is called?
                }
            }
        }
    };
});

654voto

Mark Rajcok Points 85912

Voir Quelles sont les nuances de portée prototypes / l'héritage par prototype dans AngularJS?

Pour résumer: la voie à une directive accède à son parent ($parent) champ d'application dépend du type de champ d'application de la directive crée:

  1. par défaut (scope: false) - la directive ne crée pas un nouveau champ d'application, alors il n'y a pas d'héritage ici. Du champ de la directive est la même portée que le parent/conteneur. Dans la fonction de lien, utilisez le premier paramètre (typiquement scope).

  2. scope: true - la directive crée un nouvel enfant qui fait hérite de la portée parent. Les propriétés qui sont définies sur la portée parent sont disponibles à la directive scope (en raison de prototypes d'héritage). Il suffit de se méfier de la rédaction primitive de la portée à la propriété-qui permettra de créer une nouvelle propriété sur le champ d'application de la directive (qui cache/les ombres de la portée parent propriété de même nom).

  3. scope: { ... } - la directive crée un nouveau isoler/isolé portée. Il n'a pas fait hériter de la portée parent. Vous pouvez toujours accéder au parent portée à l'aide d' $parent, mais ce n'est normalement pas recommandé. Au lieu de cela, vous devez spécifier quel parent propriétés de l'étendue (et/ou la fonction) de la directive besoins via des attributs supplémentaires sur le même élément où la directive est utilisée, à l'aide de l' =, @, et & de la notation.

  4. transclude: true - la directive crée un nouveau "transcluded" enfant de la portée, ce qui fait hérite de la portée parent. Si la directive crée également un isolat de la portée, de la transcluded et de l'isoler de la portée sont frères et sœurs. L' $parent de la propriété de chaque champ d'application références le même parent.

Le lien ci-dessus présente des exemples et des photos de tous les 4 types.

Vous ne pouvez pas accéder au champ d'application de la directive de compilation de la fonction (comme indiqué ici: https://github.com/angular/angular.js/wiki/Understanding-Directives). Vous pouvez accéder à la directive dans la fonction de lien.

Regarder:

Pour 1. et 2. ci-dessus: normalement, vous spécifiez la propriété parent de la directive besoins via un attribut $le regarder:

<div my-dir attr1="prop1"></div>

scope.$watch(attrs.attr1, function() { ... });

Si vous regardez un objet de propriété, vous aurez besoin d'utiliser $parse:

<div my-dir attr2="obj.prop2"></div>

var model = $parse(attrs.attr2);
scope.$watch(model, function() { ... });

Pour 3. ci-dessus (isoler le champ d'application), regarder le nom que vous donnez à la directive de la propriété à l'aide de l' @ ou = notation:

<div my-dir attr3="{{prop3}}" attr4="obj.prop4"></div>

scope: {
  localName3: '@attr3',
  attr4:      '='  // here, using the same name as the attribute
},
link: function(scope, element, attrs) {
   scope.$watch('localName3', function() { ... });
   scope.$watch('attr4',      function() { ... });

11voto

STEVER Points 1545
<pre><code></code><p>et vous aurez la même portée (avec élément parent)</p><pre><code></code></pre><p></pre>

8voto

ANewcomer Points 411

Voici une astuce que j’ai utilisé une fois : créez une directive « factice » pour tenir la portée parente et placez-le quelque part en dehors de la directive désirée. Quelque chose comme :

Et puis

Peut-être pas la solution plus gracieuse, mais il fait le travail.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X