Czy mogę wprowadzić usługę do dyrektywy w AngularJS?

234

Próbuję wprowadzić usługę do dyrektywy, takiej jak poniżej:

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

Ale to zwraca mi błąd Unknown provider: myDataProvider. Czy ktoś mógłby zajrzeć do kodu i powiedzieć, czy robię coś źle?

Wyjątek
źródło

Odpowiedzi:

388

Możesz zrobić zastrzyk do dyrektyw i wygląda to tak samo jak wszędzie indziej.

app.directive('changeIt', ['myData', function(myData){
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            scope.name = myData.name;
        }
    }
 }]);
grecki
źródło
13
Myślę, że jest to lepsze rozwiązanie, ponieważ działa nawet po zminimalizowaniu kodu.
czerasz
5
Musiałem dodać „_myData = myData” przed zwróceniem {}, a następnie odwołać się do obiektu jako _myData wewnątrz funkcji link.
Jelling
Dzięki @Jelling. Musiałem zrobić to samo. Zastanawiam się, czy ktokolwiek mógłby nam powiedzieć, dlaczego ...?
sfletche
6
jakiś konkretny powód, aby wstawić $ compile do dyrektywy? nigdzie się nie wydaje.
gru
4
Czy istnieje rozwiązanie do wstrzykiwania, jeśli chcesz utworzyć funkcję link poza wywołaniem dyrektywy?
ThinkBonobo,
19

Zmień definicję dyrektywy z app.modulena app.directive. Poza tym wszystko wygląda dobrze. Przy okazji bardzo rzadko trzeba wstrzykiwać usługę do dyrektywy. Jeśli wstrzykujesz usługę (która zwykle jest źródłem danych lub modelem) do swojej dyrektywy (która jest rodzajem widoku), tworzysz bezpośrednie połączenie między twoim widokiem a modelem. Musisz je oddzielić, łącząc je za pomocą kontrolera.

Działa dobrze. Nie jestem pewien, co robisz, co jest złe. Oto część z tego działa.

http://plnkr.co/edit/M8omDEjvPvBtrBHM84Am

ganaraj
źródło
Czy możesz podać przykład
wyjątek
@Exception Czy umieścisz swój kod w skrzypcach? Mogę rzucić okiem i zobaczyć, dlaczego twój kod nie działa i prawdopodobnie pomogę ci to naprawić.
ganaraj
@Exception dodał działający wykres pokazujący działający kod.
ganaraj
3
Właśnie odkryłem coś: jeśli zdefiniujesz zastrzyk w parametrach funkcji, function($location) { ...ale tak naprawdę nie odwołujesz się do $locationfunkcji, AngularJS nie wykona wstrzyknięcia. Jedyny raz, kiedy zauważysz to zachowanie, znajduje się w debuggerze.
Walter Stabosz
13
Nie jestem pewien, czy zgadzam się z twoim komentarzem „połączonym”. Łączymy już kontroler i usługę globalnie - nie możemy programowo zastąpić implementacji usługi w czasie wykonywania. Co oznacza, że ​​pojedynczy kontroler otrzymuje jedną usługę. Jednak - dyrektywy mają izolowaną konfigurację dla poszczególnych tagów na stronie, więc potencjalnie umożliwiamy różne usługi dla różnych instancji dyrektywy. Wydaje mi się, że jest to mniej oddzielone od siebie.
facet mograbi
11

Możesz także skorzystać z usługi $ inject, aby uzyskać dowolną usługę. Uważam to za przydatne, jeśli nie znam nazwy usługi z wyprzedzeniem, ale znam interfejs usługi. Na przykład dyrektywa, która połączy tabelę z punktem końcowym ngResource lub ogólny przycisk usuwania-zapisu, który współdziała z dowolnym punktem końcowym interfejsu API. Nie chcesz ponownie wdrażać dyrektywy tabelowej dla każdego kontrolera lub źródła danych.

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)

teraz Twoja „anonimowa” usługa jest w pełni dostępna. Jeśli na przykład jest to ngResource, możesz użyć standardowego interfejsu ngResource, aby uzyskać dane

Na przykład:

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

Uważam, że ta technika jest bardzo przydatna podczas tworzenia elementów, które szczególnie współdziałają z punktami końcowymi interfejsu API.

Tyrone Wilson
źródło