Могу ли я добавить сервис в директиву AngularJS?

234

Я пытаюсь внедрить службу в директиву, как показано ниже:

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

Но это возвращает мне ошибку Unknown provider: myDataProvider. Может кто-нибудь, пожалуйста, посмотрите код и скажите мне, если я делаю что-то не так?

исключение
источник

Ответы:

388

Вы можете делать инъекции в Директивах, и это выглядит так же, как и везде.

app.directive('changeIt', ['myData', function(myData){
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            scope.name = myData.name;
        }
    }
 }]);
grendian
источник
13
Я думаю, что это лучшее решение, потому что оно работает даже после минимизации вашего кода.
Череш
5
Мне пришлось добавить _myData = myData до возврата {}, а затем ссылаться на объект как _myData внутри функции ссылки.
Jelling
Спасибо @ Джеллинг. Я должен был сделать то же самое. Интересно, кто-нибудь может сказать нам, почему ...?
sfletche
6
какая-то конкретная причина для внедрения $ compile в директиву? кажется, он нигде не используется.
гру
4
Есть ли решение для инъекции, если вы хотите создать функцию связи вне вызова директивы?
ThinkBonobo
19

Измените определение вашей директивы с app.moduleна app.directive. Кроме того, все выглядит хорошо. Кстати, очень редко вам приходится вводить услугу в директиву. Если вы внедряете сервис (который обычно является источником данных или моделью) в вашу директиву (которая является частью представления), вы создаете прямую связь между вашим представлением и моделью. Вы должны отделить их, соединяя их вместе с помощью контроллера.

Это работает нормально. Я не уверен, что вы делаете, что неправильно. Вот его работа.

http://plnkr.co/edit/M8omDEjvPvBtrBHM84Am

ganaraj
источник
Можете ли вы привести пример, пожалуйста
Исключение
@Exception Можете ли вы поместить свой код в скрипку? Я могу взглянуть и понять, почему ваш код не работает, и, вероятно, помочь вам исправить это.
ганарадж
@Exception добавил рабочий план, который показывает работающий код.
Ганарадж
3
Я только что обнаружил: если вы определяете внедрение в параметрах функции, function($location) { ...но на самом деле не ссылаетесь $locationвнутри функции, AngularJS не будет выполнять внедрение. Единственный раз, когда вы заметите такое поведение, находится внутри отладчика.
Вальтер Стабош
13
Я не уверен, что согласен с вашим «спаренным» комментарием. Мы уже соединяем контроллер и сервис по всему миру - мы не можем программно заменить реализацию сервиса во время выполнения. Это означает, что один контроллер получает один сервис. Однако директивы имеют отдельную конфигурацию для каждого тега на странице, поэтому потенциально мы можем включить разные службы для разных экземпляров директив. Мне кажется, это менее разделено.
парень mograbi
11

Вы также можете использовать сервис $ inject, чтобы получить любой сервис, который вам нравится. Я считаю это полезным, если я не знаю название службы заранее, но знаю интерфейс службы. Например, директива, которая вставит таблицу в конечную точку ngResource, или общая кнопка удаления записи, которая взаимодействует с любой конечной точкой API. Вы не хотите повторно реализовывать директиву table для каждого контроллера или источника данных.

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)

Теперь ваша анонимная услуга полностью доступна. Если это, например, ngResource, вы можете использовать стандартный интерфейс ngResource для получения ваших данных.

Например:

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

Я нашел эту технику очень полезной при создании элементов, особенно взаимодействующих с конечными точками API.

Тайрон Уилсон
источник