Kann ich einen Dienst in eine Direktive in AngularJS einfügen?


234

Ich versuche, einen Dienst in eine Richtlinie wie die folgende einzufügen:

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

Aber das gibt mir einen Fehler zurück Unknown provider: myDataProvider. Könnte jemand bitte in den Code schauen und mir sagen, wenn ich etwas falsch mache?

Antworten:


388

Sie können Direktiven injizieren, und es sieht genauso aus wie überall sonst.

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

13
Ich denke, dies ist eine bessere Lösung, da es auch nach dem Minimieren Ihres Codes funktioniert.
Czerasz

5
Ich musste vor der Rückgabe {} '_myData = myData' hinzufügen und dann das Objekt innerhalb der Link-Funktion als _myData referenzieren.
Jelling

Danke @Jelling. Ich musste das Gleiche tun. Ich frage mich, ob uns da draußen jemand sagen könnte, warum ...?
Sfletche

6
Gibt es einen bestimmten Grund, $ compile in die Direktive einzufügen? es scheint nirgendwo verwendet zu werden.
gru

4
Gibt es eine Lösung für das Injizieren, wenn Sie die Link-Funktion außerhalb des Direktivenaufrufs erstellen möchten?
ThinkBonobo

19

Ändern Sie Ihre Direktivendefinition von app.modulenach app.directive. Ansonsten sieht alles gut aus. Übrigens müssen Sie sehr selten einen Dienst in eine Richtlinie einfügen. Wenn Sie einen Dienst (der normalerweise eine Datenquelle oder ein Modell ist) in Ihre Direktive (die Teil einer Ansicht ist) einfügen, erstellen Sie eine direkte Kopplung zwischen Ihrer Ansicht und Ihrem Modell. Sie müssen sie trennen, indem Sie sie mit einem Controller miteinander verbinden.

Es funktioniert gut. Ich bin nicht sicher, was Sie tun, was falsch ist. Hier funktioniert ein Teil davon.

http://plnkr.co/edit/M8omDEjvPvBtrBHM84Am


Können Sie bitte ein Beispiel geben
Ausnahme

@Exception Kannst du deinen Code in eine Geige stecken? Ich kann nachsehen, warum Ihr Code nicht funktioniert, und Ihnen wahrscheinlich dabei helfen, ihn zu beheben.
Ganaraj

@Exception hat einen funktionierenden Plunk hinzugefügt, der zeigt, wie der Code funktioniert.
Ganaraj

3
Ich habe gerade etwas entdeckt: Wenn Sie eine Injektion in den Funktionsparametern definieren, sich function($location) { ...aber nicht auf $locationdie Funktion beziehen , führt AngularJS die Injektion nicht durch. Das einzige Mal, dass Sie dieses Verhalten jemals bemerken würden, ist im Debugger.
Walter Stabosz

13
Ich bin nicht sicher, ob ich Ihrem "gekoppelten" Kommentar zustimme. Wir koppeln den Controller und den Service bereits global - wir können die Implementierung des Service zur Laufzeit nicht programmatisch ersetzen. Dies bedeutet, dass ein einzelner Controller einen einzelnen Dienst erhält. Direktiven haben jedoch eine isolierte Konfiguration pro Tag auf der Seite, sodass wir möglicherweise unterschiedliche Dienste für unterschiedliche Direktiveninstanzen aktivieren. Mir scheint, das ist weniger entkoppelt.
Kerl Mograbi

11

Sie können auch den $ inj-Service verwenden, um den gewünschten Service zu erhalten. Ich finde das nützlich, wenn ich den Dienstnamen nicht im Voraus kenne, aber die Dienstschnittstelle kenne. Zum Beispiel eine Direktive, die eine Tabelle in einen ngResource-Endpunkt einfügt, oder eine generische Schaltfläche zum Löschen von Datensätzen, die mit einem beliebigen API-Endpunkt interagiert. Sie möchten die Tabellenanweisung nicht für jeden Controller oder jede Datenquelle erneut implementieren.

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)

Jetzt ist Ihr "anonymer" Dienst vollständig verfügbar. Wenn es sich beispielsweise um ngResource handelt, können Sie die Standardschnittstelle ngResource verwenden, um Ihre Daten abzurufen

Beispielsweise:

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

Ich habe festgestellt, dass diese Technik sehr nützlich ist, wenn Elemente erstellt werden, die insbesondere mit API-Endpunkten interagieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.