Uma diretiva angular pode passar argumentos para funções em expressões especificadas nos atributos da diretiva?

Eu tenho uma diretiva de formulário que usa um atributo de callback especificado com um escopo de isolar:

 scope: { callback: '&' } 

Ele fica dentro de um ng-repeat então a expressão que eu passo inclui o id do object como um argumento para a function callback:

  

Quando terminei com a diretiva, ele chama $scope.callback() de sua function de controlador. Para a maioria dos casos, isso é bom, e é tudo que eu quero fazer, mas às vezes eu gostaria de adicionar outro argumento de dentro da própria directive .

Existe uma expressão angular que permitiria isso: $scope.callback(arg2) , resultando em callback sendo chamado com arguments = [item.id, arg2] ?

Se não, qual é a melhor maneira de fazer isso?

Eu descobri que isso funciona:

  

Com

 scope { callback: '=', callbackArg: '=' } 

e a diretiva chamando

 $scope.callback.apply(null, [$scope.callbackArg].concat([arg2, arg3]) ); 

Mas eu não acho que é particularmente legal e envolve colocar coisas extras no escopo isolado.

Existe uma maneira melhor?

Plunker playground aqui (tem o console aberto).

Se você declarar seu retorno de chamada como mencionado por @ lex82 como

 callback = "callback(item.id, arg2)" 

Você pode chamar o método de retorno de chamada no escopo da diretiva com o mapa de objects e ele faria a binding corretamente. Gostar

 scope.callback({arg2:"some value"}); 

sem exigir por $ parse. Veja meu violino (log do console) http://jsfiddle.net/k7czc/2/

Atualização : Há um pequeno exemplo disso na documentação :

& ou & attr – fornece uma maneira de executar uma expressão no contexto do escopo pai. Se nenhum nome de atributo for especificado, o nome do atributo será o mesmo que o nome local. Dado e definição de escopo de widget: {localFn: ‘& myAttr’}, então isolar a propriedade de escopo localFn apontará para um wrapper de function para a expressão count = count + value. Muitas vezes é desejável transmitir dados do escopo isolado por meio de uma expressão e para o escopo pai, isso pode ser feito passando um mapa de nomes e valores de variables ​​locais para o wrapper de expressão fn. Por exemplo, se a expressão for increment (amount), podemos especificar o valor da quantia chamando o localFn como localFn ({amount: 22}).

Nada de errado com as outras respostas, mas eu uso a seguinte técnica ao passar funções em um atributo de diretiva.

Deixe de fora o parêntese ao include a diretiva no seu html:

  

Em seguida, descompacte a function no link ou no controlador de sua diretiva. aqui está um exemplo:

 app.directive("myDirective", function() { return { restrict: "E", scope: { callback: "&" }, template: "
", // call function this way... link: function(scope, element, attrs) { // unwrap the function scope.callback = scope.callback(); scope.data = "data from somewhere"; element.bind("click",function() { scope.$apply(function() { callback(data); // ...or this way }); }); } } }]);

A etapa “desembrulhar” permite que a function seja chamada usando uma syntax mais natural. Ele também garante que a diretiva funcione corretamente mesmo quando aninhada em outras diretivas que possam passar pela function. Se você não fez o desembrulhar, então se você tiver um cenário como este:

      

Então você acabaria com algo assim em sua diretiva interna:

 callback()()()(data); 

O que falharia em outros cenários de aninhamento.

Eu adaptei esta técnica de um excelente artigo de Dan Wahlin em http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters

Eu adicionei a etapa de desembrulhar para tornar a chamada da function mais natural e resolver o problema de aninhamento que encontrei em um projeto.

Na diretiva ( myDirective ):

 ... directive.scope = { boundFunction: '&', model: '=', }; ... return directive; 

No modelo de diretiva:

 
{{item.myValue}}

Na fonte:

   

… onde myFunction é definido no controlador.

Observe que o param no modelo de diretiva se liga perfeitamente ao param na origem e está definido como item .


Para chamar de dentro da propriedade link de uma diretiva (“inside” dela), use uma abordagem muito similar:

 ... directive.link = function(isolatedScope) { isolatedScope.boundFunction({param: "foo"}); }; ... return directive; 

Sim, existe uma maneira melhor: você pode usar o serviço $ parse em sua diretiva para avaliar uma expressão no contexto do escopo pai enquanto vincula determinados identificadores na expressão a valores visíveis somente dentro de sua diretiva:

 $parse(attributes.callback)(scope.$parent, { arg2: yourSecondArgument }); 

Adicione esta linha à function de link da diretiva onde você pode acessar os atributos da diretiva.

Seu atributo de retorno de chamada pode então ser definido como callback = "callback(item.id, arg2)" porque arg2 é ligado ao seuSecondArgument pelo serviço $ parse dentro da diretiva. Diretivas como ng-click permitem acessar o evento click por meio do identificador $event dentro da expressão passada para a diretiva usando exatamente esse mecanismo.

Observe que você não precisa tornar o callback um membro de seu escopo isolado com essa solução.