web-dev-qa-db-fra.com

Passer la variable au modèle de directive sans créer de nouvelle portée

Existe-t-il un moyen de transmettre des variables utilisant des attributs à une directive sans créer de nouvelle portée?

HTML

<div ng-click='back()' button='go back'></div>

JS

.directive('button', function () {
    return {
        scope: {
            button: '@'
        },
        template: "<div><div another-directive></div>{{button}}</div>",
        replace: true
    }
})

Le problème est que la ng-click='back()' fait désormais référence à la portée de la directive. Je peux toujours faire ng-click='$parent.back()' mais ce n'est pas ce que je veux.

27
Seb Fanals

Par défaut, les directives ne créent pas de nouvelle étendue. Si vous voulez rendre cela explicite, ajoutez scope: false À votre directive:

<div ng-click='back()' button='go back!'></div>
angular.module('myApp').directive("button", function () {
    return {
        scope: false,  // this is the default, so you could remove this line
        template: "<div><div another-directive></div>{{button}}</div>",
        replace: true,
        link: function (scope, element, attrs) {
           scope.button = attrs.button;
        }
    };
});

fiddle

Puisqu'une nouvelle propriété, button, est en cours de création sur la portée, vous devez normalement créer une nouvelle portée enfant en utilisant scope: true Comme @ ardentum-c l'a fait dans sa réponse. La nouvelle portée héritera prototypiquement de la portée parent, c'est pourquoi vous n'avez pas besoin de mettre $parent.back() dans votre HTML.

Une autre petite chose à mentionner: même si nous utilisons replace: true, Cliquer sur l'élément appelle toujours back(). Cela fonctionne car "le processus de remplacement migre tous les attributs/classes de l'ancien élément vers le nouveau". - directive doc
Donc ng-click='back()' button='go back!' est migré vers le premier div dans le modèle de la directive.

33
Mark Rajcok

Je suppose que vous devez utiliser la fonction de compilation dans ce cas.

angular.module('myApp').directive("button", function () {
    return {
        template: "<div><div another-directive></div>{{button}}</div>",
        replace: true,
        scope:   true,
        compile: function (tElement, tAttrs) {
            // this is link function
            return function (scope) {
                scope.button = tAttrs.button;
            };            
        }
    };
});

Voici exemple jsfiddle .

2
ardentum-c