166 votes

AngularJS - passer une fonction à une directive

J'ai un exemple angularJS

<div ng-controller="testCtrl">

<test color1="color1" updateFn="updateFn()"></test>
</div>
 <script>
  angular.module('dr', [])
.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function() {
        alert('123');
    }
})
.directive('test', function() {
    return {
        restrict: 'E',
        scope: {color1: '=',
                updateFn: '&'},
        template: "<button ng-click='updateFn()'>Click</button>",
        replace: true,
        link: function(scope, elm, attrs) { 
        }
    }
});

</script>
</body>

</html>

Je veux que lorsque je clique sur le bouton, la boîte d'alerte apparaisse, mais rien ne s'affiche.

Quelqu'un peut-il m'aider ?

253voto

CodeHater Points 13377

Pour appeler une fonction de contrôleur dans la portée parent à partir d'une directive de portée isolée, utilisez dash-separated les noms d'attributs dans le HTML comme le dit le PO.

De même, si vous voulez envoyer un paramètre à votre fonction, appelez la fonction en passant un objet :

<test color1="color1" update-fn="updateFn(msg)"></test>

JS

var app = angular.module('dr', []);

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='updateFn({msg : \"Hello World!\"})'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {             
        }
    }
});

<strong><a href="http://jsfiddle.net/yMHe4/">Fiddle</a></strong>

164voto

steve Points 1837

Peut-être que j'ai raté quelque chose, mais bien que les autres solutions appellent la fonction de la portée parentale, il n'est pas possible de passer des arguments à partir du code de la directive, parce que la fonction update-fn appelle updateFn() avec des paramètres fixes, dans par exemple {msg: "Hello World"} . Une légère modification permet à la directive de passer des arguments, ce qui, à mon avis, est beaucoup plus utile.

<test color1="color1" update-fn="updateFn"></test>

Notez que le HTML passe une référence de fonction, c'est-à-dire sans () des crochets.

JS

var app = angular.module('dr', []);

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='callUpdate()'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {       
          scope.callUpdate = function() {
            scope.updateFn()("Directive Args");
          }
        }
    }
});

Donc, dans l'exemple ci-dessus, le HTML appelle la portée locale. callUpdate qui va ensuite "chercher" la fonction updateFn dans l'étendue parent et appelle la fonction renvoyée avec des paramètres que la directive peut générer.

http://jsfiddle.net/mygknek2/

39voto

Ofer Segev Points 131

Dans la balise Html de votre directive 'test', le nom de l'attribut de la fonction ne devrait pas être en minuscules, mais en tirets.

donc - au lieu de :

<test color1="color1" updateFn="updateFn()"></test>

écrire :

<test color1="color1" update-fn="updateFn()"></test>

C'est la façon dont Angular fait la différence entre les attributs de directive (comme la fonction update-fn) et les fonctions.

10voto

Tamás Márton Points 724

Que diriez-vous de passer la fonction de contrôleur avec liaison bidirectionnelle ? Vous pouvez alors l'utiliser dans la directive exactement de la même manière que dans un modèle ordinaire (j'ai supprimé les parties non pertinentes pour simplifier) :

<div ng-controller="testCtrl">

   <!-- pass the function with no arguments -->
   <test color1="color1" update-fn="updateFn"></test>
</div>

<script>
   angular.module('dr', [])
   .controller("testCtrl", function($scope) {
      $scope.updateFn = function(msg) {
         alert(msg);
      }
   })
   .directive('test', function() {
      return {
         scope: {
            updateFn: '=' // '=' bidirectional binding
         },
         template: "<button ng-click='updateFn(1337)'>Click</button>"
      }
   });
</script>

J'ai atterri sur cette question parce que j'ai déjà essayé la méthode ci-dessus, mais cela n'a pas fonctionné. Maintenant ça marche parfaitement.

6voto

Jane Points 66

Utilisez le tiret et les minuscules pour le nom de l'attribut (comme les autres réponses l'ont dit) :

 <test color1="color1" update-fn="updateFn()"></test>

Et utilisez "=" au lieu de "&" dans la portée des directives :

 scope: { updateFn: '='}

Vous pouvez alors utiliser updateFn comme n'importe quelle autre fonction :

 <button ng-click='updateFn()'>Click</button>

Et voilà !

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