Posso inserire un servizio in una direttiva in AngularJS?


234

Sto cercando di iniettare un servizio in una direttiva come di seguito:

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

Ma questo mi sta restituendo un errore Unknown provider: myDataProvider. Qualcuno potrebbe esaminare il codice e dirmi se sto facendo qualcosa di sbagliato?

Risposte:


388

Puoi fare l'iniezione su Direttive, e sembra che lo faccia ovunque.

app.directive('changeIt', ['myData', function(myData){
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            scope.name = myData.name;
        }
    }
 }]);

13
Penso che questa sia una soluzione migliore perché funziona anche dopo aver minimizzato il tuo codice.
Czerasz,

5
Ho dovuto aggiungere '_myData = myData' prima del ritorno {} e quindi fare riferimento all'oggetto come _myData all'interno della funzione di collegamento.
Jelling,

Grazie @Jelling. Ho dovuto fare la stessa cosa. Mi chiedo se qualcuno là fuori potrebbe dirci perché ...?
sfletche

6
qualche motivo particolare per iniettare $ compilare nella direttiva? non sembra essere usato da nessuna parte.
gru

4
Esiste una soluzione per l'iniezione se si desidera creare la funzione di collegamento al di fuori della chiamata direttiva?
ThinkBonobo,

19

Cambia la definizione della direttiva da app.modulea app.directive. A parte questo, tutto sembra a posto. A proposito, molto raramente devi iniettare un servizio in una direttiva. Se stai iniettando un servizio (che di solito è un'origine dati o un modello) nella tua direttiva (che è una specie di parte di una vista), stai creando un accoppiamento diretto tra la tua vista e il tuo modello. È necessario separarli collegandoli insieme utilizzando un controller.

Funziona benissimo. Non sono sicuro di quello che stai facendo che è sbagliato. Eccone uno che funziona.

http://plnkr.co/edit/M8omDEjvPvBtrBHM84Am


Potete fornire un esempio per favore
Eccezione

@Exception Puoi mettere il tuo codice in un violino? Posso dare un'occhiata e vedere perché il tuo codice non funziona e probabilmente ti aiuterà a risolverlo.
Ganaraj,

@Exception ha aggiunto un riquadro di lavoro che mostra il funzionamento del codice.
Ganaraj,

3
Ho appena scoperto qualcosa: se si definisce un'iniezione nei parametri della funzione, function($location) { ...ma in realtà non si fa riferimento $locationall'interno della funzione, AngularJS non eseguirà l'iniezione. L'unica volta in cui potresti mai notare questo comportamento è all'interno del debugger.
Walter Stabosz,

13
Non sono sicuro di essere d'accordo con il tuo commento "accoppiato". Associamo già il controller e il servizio a livello globale - non possiamo sostituire programmaticamente l'implementazione del servizio in fase di esecuzione. Ciò significa che un singolo controller ottiene un singolo servizio. Tuttavia - le direttive hanno una configurazione isolata per tag nella pagina, quindi potenzialmente abilitiamo un servizio diverso a diverse istanze della direttiva. Mi sembra che questo sia meno disaccoppiato.
guy mograbi,

11

Puoi anche usare il servizio $ inject per ottenere qualunque servizio ti piaccia. Lo trovo utile se non conosco in anticipo il nome del servizio ma conosco l'interfaccia del servizio. Ad esempio una direttiva che inserirà una tabella in un endpoint ngResource o in un pulsante generico di eliminazione-record che interagisce con qualsiasi end point api. Non si desidera implementare nuovamente la direttiva tabella per ogni controller o origine dati.

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)

ora il tuo servizio "anonimo" è completamente disponibile. Ad esempio, se è ngResource, è possibile utilizzare l'interfaccia standard ngResource per ottenere i dati

Per esempio:

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

Ho trovato questa tecnica molto utile quando si creano elementi che interagiscono in particolare con gli endpoint API.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.