¿Puedo inyectar un servicio en una directiva en AngularJS?

234

Estoy tratando de inyectar un servicio en una directiva como la siguiente:

 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;
            }
        }
 });

Pero esto me devuelve un error Unknown provider: myDataProvider. ¿Podría alguien mirar el código y decirme si estoy haciendo algo mal?

Excepción
fuente

Respuestas:

388

Puede inyectarse en las Directivas, y se ve igual que en cualquier otro lugar.

app.directive('changeIt', ['myData', function(myData){
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            scope.name = myData.name;
        }
    }
 }]);
Grendian
fuente
13
Creo que esta es una mejor solución porque funciona incluso después de minimizar su código.
czerasz
55
Tuve que agregar '_myData = myData' antes del retorno {} y luego hacer referencia al objeto como _myData dentro de la función de enlace.
Jelling
Gracias @Jelling. Tenía que hacer lo mismo. Me pregunto si alguien podría decirnos por qué ...
sfletche
66
¿Alguna razón particular para inyectar $ compile en la directiva? no parece ser usado en ningún lado.
gru
44
¿Hay alguna solución para inyectar si desea crear la función de enlace fuera de la llamada directiva?
ThinkBonobo
19

Cambie su definición de directiva de app.modulea app.directive. Aparte de eso, todo se ve bien. Por cierto, muy raramente tienes que inyectar un servicio en una directiva. Si está inyectando un servicio (que generalmente es una fuente de datos o modelo) en su directiva (que es parte de una vista), está creando un acoplamiento directo entre su vista y modelo. Debe separarlos conectándolos entre sí mediante un controlador.

Funciona bien No estoy seguro de lo que estás haciendo, lo cual está mal. Aquí hay una parte de esto funcionando.

http://plnkr.co/edit/M8omDEjvPvBtrBHM84Am

ganaraj
fuente
¿Puede dar un ejemplo, por favor
Excepción
@Exception ¿Puedes poner tu código en un violín? Puedo echar un vistazo y ver por qué su código no funciona y probablemente ayudarlo a solucionarlo.
ganaraj
@Exception agregó un plunk funcional que muestra el código funcionando.
ganaraj
3
Acabo de descubrir algo: si define una inyección en los parámetros de la función, function($location) { ...pero en realidad no se refiere al $locationinterior de la función, AngularJS no realizará la inyección. La única vez que notará este comportamiento es dentro del depurador.
Walter Stabosz
13
No estoy seguro de estar de acuerdo con su comentario "acoplado". Ya combinamos el controlador y el servicio a nivel mundial; no podemos reemplazar programáticamente la implementación del servicio en tiempo de ejecución. Lo que significa que un solo controlador obtiene un solo servicio. Sin embargo, las directivas tienen una configuración aislada por etiqueta en la página, por lo que potencialmente habilitamos diferentes servicios para diferentes instancias de directivas. Me parece que esto está menos desacoplado.
Guy Mograbi
11

También puede usar el servicio $ inject para obtener el servicio que desee. Me resulta útil si no conozco el nombre del servicio con anticipación pero conozco la interfaz del servicio. Por ejemplo, una directiva que conectará una tabla en un punto final ngResource o un botón genérico de borrar registro que interactúa con cualquier punto final de la API. No desea volver a implementar la directiva de tabla para cada controlador o fuente de datos.

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)

ahora su servicio 'anónimo' está completamente disponible. Si es ngResource, por ejemplo, puede usar la interfaz estándar ngResource para obtener sus datos

Por ejemplo:

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

He encontrado que esta técnica es muy útil al hacer elementos que interactúan especialmente con puntos finales API.

Tyrone Wilson
fuente