Posso injetar um serviço em uma diretiva no AngularJS?

234

Estou tentando injetar um serviço em uma diretiva como abaixo:

 var app = angular.module('app',[]);
 app.factory('myData', function(){
     return {
        name : "myName"
     }
 });
 app.directive('changeIt',function($compile, myData){
    return {
            restrict: 'C',
            link: function (scope, element, attrs) {
                scope.name = myData.name;
            }
        }
 });

Mas isso está me devolvendo um erro Unknown provider: myDataProvider . Alguém poderia procurar no código e me dizer se estou fazendo algo errado?

Exceção
fonte

Respostas:

388

Você pode injetar diretivas e parece exatamente como em qualquer outro lugar.

app.directive('changeIt', ['myData', function(myData){
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            scope.name = myData.name;
        }
    }
 }]);
grendian
fonte
13
Eu acho que essa é uma solução melhor porque funciona mesmo depois de minificar seu código.
Czerasz
5
Eu tive que adicionar '_myData = myData' antes do retorno {} e depois referenciar o objeto como _myData dentro da função de link.
Jelling
Obrigado @Jelling. Eu tive de fazer a mesma coisa. Gostaria de saber se alguém lá fora poderia nos dizer por que ...?
precisa
6
alguma razão específica para injetar $ compile na diretiva? não parece ser usado em lugar algum.
gru
4
Existe uma solução para injetar se você deseja criar a função de link fora da chamada de diretiva?
precisa saber é o seguinte
19

Altere sua definição de diretiva de app.modulepara app.directive. Além disso, tudo parece bem. Aliás, muito raramente você precisa injetar um serviço em uma diretiva. Se você estiver injetando um serviço (que geralmente é uma fonte ou modelo de dados) em sua diretiva (que faz parte de uma visualização), estará criando um acoplamento direto entre sua visualização e modelo. Você precisa separá-los conectando-os usando um controlador.

Funciona bem. Não sei ao certo o que você está fazendo, o que está errado. Aqui está uma parte dele funcionando.

http://plnkr.co/edit/M8omDEjvPvBtrBHM84Am

ganaraj
fonte
Você pode fornecer um exemplo, por favor
Exceção
@ Exception Você pode colocar seu código em um violino? Posso dar uma olhada e ver por que seu código não está funcionando e provavelmente ajudá-lo a corrigi-lo.
22313 Ganaraj
A @Exception adicionou um argumento que mostra o código funcionando.
22313 Ganaraj
3
Acabei de descobrir uma coisa: se você definir uma injeção nos parâmetros da função, function($location) { ...mas na verdade não fizer referência a ela $location, o AngularJS não executará a injeção. A única vez em que você perceberia esse comportamento seria no depurador.
Walter Stabosz
13
Não sei se concordo com o seu comentário "acoplado". Já associamos o controlador e o serviço globalmente - não podemos substituir programaticamente a implementação do serviço em tempo de execução. O que significa que um único controlador obtém um único serviço. No entanto - as diretivas possuem uma configuração isolada por tag na página; portanto, potencialmente habilitamos serviços diferentes para diferentes instâncias de diretiva. Parece-me que isso é menos dissociado.
cara Mograbi
11

Você também pode usar o serviço $ injetar para obter o serviço que desejar. Acho isso útil se não souber o nome do serviço antes, mas conhecer a interface do serviço. Por exemplo, uma diretiva que irá conectar uma tabela a um ponto final ngResource ou a um botão de exclusão / registro genérico que interaja com qualquer ponto final api. Você não deseja reimplementar a diretiva de tabela para cada controlador ou fonte de dados.

template.html

<div my-directive api-service='ServiceName'></div>

my-directive.directive.coffee

angular.module 'my.module'
  .factory 'myDirective', ($injector) ->
    directive = 
      restrict: 'A'
      link: (scope, element, attributes) ->
        scope.apiService = $injector.get(attributes.apiService)

agora o seu serviço 'anônimo' está totalmente disponível. Se for ngResource, por exemplo, você poderá usar a interface ngResource padrão para obter seus dados

Por exemplo:

scope.apiService.query((response) ->
  scope.data = response
, (errorResponse) ->
  console.log "ERROR fetching data for service: #{attributes.apiService}"
  console.log errorResponse.data
)

Eu descobri que essa técnica é muito útil ao criar elementos que interagem especialmente com os pontos de extremidade da API.

Tyrone Wilson
fonte