100 votes

fonction d'appel de directive angularjs spécifiée dans l'attribut et lui passant un argument

Je veux créer une directive qui renvoie à un attribut. L'attribut spécifie la fonction qui doit être appelée sur le champ. Mais j'ai aussi envie de passer un argument à la fonction qui est déterminé à l'intérieur de la fonction de lien.

<div my-method='theMethodToBeCalled'></div>

Dans la fonction link-je lier à un événement jQuery, qui passe un argument j'ai besoin de passer à la fonction:

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     var expressionHandler = $parse(attr.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        id = // some function called to determine id based on rowid
        scope.$apply(function() {expressionHandler(id);});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}

Sans passer l'id je peux le faire, mais dès que j'essaie de passer un argument, la fonction n'est pas appelée plus

98voto

johans Points 722

Marko solution fonctionne bien.

Pour contraster avec recommandé Angulaire façon (comme indiqué par treeface de plunkr) est d'utiliser un callback expression qui ne nécessite pas la définition de la expressionHandler. Dans marko l'exemple de modification:

Dans le modèle

<div my-method="theMethodToBeCalled(myParam)"></div>

Dans la directive fonction de lien

$(element).click(function( e, rowid ) {
  scope.method({myParam: id});
});

Cela a un inconvénient par rapport à marko de la solution lors du premier chargement theMethodToBeCalled fonction sera appelée avec myParam === undefined.

Un travail exampe peut être trouvé à @treeface Plunker

93voto

Robert Bak Points 3050

Juste pour ajouter un peu d'info pour les autres réponses à l'aide de & est un bon moyen si vous avez besoin d'un isolé portée.

Le principal inconvénient de marko solution est qu'il vous oblige à créer un isolé portée sur un élément, mais vous ne pouvez avoir un de ceux sur un élément (sinon vous aurez une erreur angulaire: Plusieurs directives [directive1 relative, directive2] demandent isolé portée)

Cela signifie que vous :

  • ne pouvez pas l'utiliser sur un élément de chapeau a un isolé champ d'application elle-même
  • ne pouvez pas utiliser deux directives avec cette solution sur le même élément

Puisque la question initiale utilise une directive à l' restrict:'A' deux situations peuvent se produire assez souvent dans des applications plus importantes, et en utilisant un cas isolé portée ici n'est pas une bonne pratique et aussi inutile. En fait rekna eu une bonne intuition dans ce cas, et avait presque de travail, la seule chose qu'il faisait de mal a appeler la $analysé la fonction incorrect (voir de quoi il en retourne ici: https://docs.angularjs.org/api/ng/service/$parse ).

TL;DR; Fixe question code de

<div my-method='theMethodToBeCalled(id)'></div>

et le code

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     // here you can parse any attribute (so this could as well be,
     // myDirectiveCallback or multiple ones if you need them )
     var expressionHandler = $parse(attrs.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        calculatedId = // some function called to determine id based on rowid

        // HERE: call the parsed function correctly (with scope AND params object)
        expressionHandler(scope, {id:calculatedId});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}

87voto

marko Points 1166

Ne sachant pas exactement ce que vous voulez faire... mais encore, voici une solution possible.

Créer un champ avec un '&'-propriété dans le domaine local. Il "fournit un moyen pour exécuter une expression dans le contexte de la portée parent" (voir la directive de la documentation pour les détails).

J'ai aussi remarqué que vous avez utilisé un raccourci fonction de liaison et poussé dans les attributs de l'objet. Vous ne pouvez pas le faire. Il est plus clair (à mon humble avis) il suffit de retourner la directive-définition de l'objet. Voir mon code ci-dessous.

Voici un exemple de code et un violon.

<div ng-app="myApp">
<div ng-controller="myController">
    <div my-method='theMethodToBeCalled'>Click me</div>
</div>
</div>

<script>

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

   app.directive("myMethod",function($parse) {
       var directiveDefinitionObject = {
         restrict: 'A',
         scope: { method:'&myMethod' },
         link: function(scope,element,attrs) {
            var expressionHandler = scope.method();
            var id = "123";

            $(element).click(function( e, rowid ) {
               expressionHandler(id);
            });
         }
       };
       return directiveDefinitionObject;
   });

   app.controller("myController",function($scope) {
      $scope.theMethodToBeCalled = function(id) { 
          alert(id); 
      };
   });

</script>

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