Je n'arrive pas à trouver un moyen d'appeler une fonction sur la portée parent à partir d'une directive sans utiliser la portée isolée. Je sais que si j'utilise une portée isolée, je peux simplement utiliser "&" dans la portée isolée pour accéder à la fonction sur la portée parente, mais l'utilisation de la portée isolée quand ce n'est pas nécessaire a des conséquences. Considérez le code HTML suivant:
<button ng-hide="hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button>
Dans cet exemple simple, je veux afficher une boîte de dialogue de confirmation JavaScript et n'appeler doIt () que s'ils cliquent sur "OK" dans la boîte de dialogue de confirmation. C'est simple en utilisant une portée isolée. La directive ressemblerait à ceci:
.directive('confirm', function () {
return {
restrict: 'A',
scope: {
confirm: '@',
confirmAction: '&'
},
link: function (scope, element, attrs) {
element.bind('click', function (e) {
if (confirm(scope.confirm)) {
scope.confirmAction();
}
});
}
};
})
Mais le problème est que, parce que j'utilise une portée isolée, ng-hide dans l'exemple ci-dessus ne s'exécute plus contre la portée parente , mais plutôt dans la portée isolée (car l'utilisation d'une portée isolée sur n'importe quelle directive entraîne toutes les directives sur cet élément à utilisez la portée isolée). Voici un jsFiddle de l'exemple ci-dessus où ng-hide ne fonctionne pas. (Notez que dans ce violon, le bouton doit se cacher lorsque vous tapez "oui" dans la zone de saisie.)
L'alternative serait de NE PAS utiliser un champ d'application isolé , ce que je souhaite vraiment ici, car il n'est pas nécessaire que le champ d'application de cette directive soit isolé. Le seul problème que j'ai est, comment appeler une méthode sur la portée parent si je ne la transmets pas sur une portée isolée ?
Voici un jsfiddle où je n'utilise PAS de portée isolée et le ng-hide fonctionne bien, mais, bien sûr, l'appel à confirmAction () ne fonctionne pas, et je ne sais pas comment le faire fonctionner.
Veuillez noter que la réponse que je recherche vraiment est de savoir comment appeler des fonctions sur la portée externe SANS utiliser une portée isolée. Et je ne suis pas intéressé à faire fonctionner ce dialogue de confirmation d'une autre manière, car le but de cette question est de comprendre comment faire des appels à la portée externe et toujours pouvoir faire fonctionner d'autres directives contre la portée parente.
Sinon, je serais intéressé d'entendre des solutions qui utilisent une portée isolée si d'autres directives fonctionnent toujours contre la portée parente , mais je ne pense pas que cela soit possible.
la source
Réponses:
Puisque la directive n'appelle qu'une fonction (et n'essaye pas de définir une valeur sur une propriété), vous pouvez utiliser $ eval au lieu de $ parse (avec une portée non isolée):
Ou mieux, utilisez simplement $ apply , ce qui permettra à $ eval () de comparer son argument à la portée:
Violon
la source
confirm-action="doIt(arg1)"
puis les définirscope.arg1
avant d'appeler $ eval. Cependant, il serait probablement plus propre d'utiliser $ parse: stackoverflow.com/a/16200618/215945scope.$eval(attrs.confirmAction({arg1: 'blah'})
ne fonctionnera pas. Vous devrez utiliser $ parse avec cette syntaxe.Vous souhaitez utiliser le service $ parse dans AngularJS.
Donc pour votre exemple:
Il y a un problème avec la définition d'une propriété à l'aide de $ parse, mais je vous laisserai traverser ce pont lorsque vous y arriverez.
la source
scope:true
) ne fonctionne car la directive ne créera pas du tout de nouvelle portée, et donc lascope
propriété que vous référencez dans lalink
fonction est exactement la même portée que la portée «parent» précédemment.Appelez explicitement
hideButton
la portée parent.Voici le violon: http://jsfiddle.net/pXej2/5/
Et voici le HTML mis à jour:
la source
Tout d'abord, un petit point: dans ce cas, le champ d'application du contrôleur externe n'est pas le champ d'application parent du champ d'application de la directive; le champ d'application du contrôleur externe est le champ d'application de la directive. En d'autres termes, les noms de variables utilisés dans la directive seront recherchés directement dans la portée du contrôleur.
Ensuite, l'écriture
attrs.confirmAction()
ne fonctionne pas carattrs.confirmAction
pour ce bouton,est la chaîne
"doIt()"
, et vous ne pouvez pas appeler une chaîne, par exemple"doIt()"()
.Votre question est vraiment:
En JavaScript, vous appelez principalement des fonctions en utilisant la notation par points, comme ceci:
Mais vous pouvez également utiliser la notation de tableau:
Notez que la valeur d'index est une chaîne . Donc, dans votre directive, vous pouvez simplement faire ceci:
la source