Не удается извлечь инжектор из углового


у меня есть приложение с двумя модулями:

angular.module('components', []).directive('foo', function () { return {};});
angular.module('gaad', ['components']);

есть куча директив, связанных с этими модулями, которые я здесь не включаю. Приложение работает нормально. Однако, когда я пытаюсь получить инжектор для модуля gaad:

var injector = angular.injector(['gaad', 'components']); //called after 'gaad' module initialization

возникает ошибка:

Uncaught Error: Unknown provider: $compileProvider from components 

приложения довольно большой, и я понятия не имею, где я должен искать ошибки. Так что мой вопрос:что может быть причиной моего проблемы?

EDIT: Я смог воспроизвести свою проблему:http://jsfiddle.net/selbh/ehmnt/11/

3 51

3 ответа:

прежде чем ответить на вопрос, мы должны отметить, что есть только один экземпляр инжектора на приложение, а не на модуль. В этом смысле невозможно получить инжектор для каждого модуля. Конечно, если мы возьмем модуль верхнего уровня, он представляет собой все приложение. В этом смысле приложение и модуль верхнего уровня кажутся эквивалентными. Это может показаться тонкой разницей, но важно понять, чтобы полностью и правильно ответить на этот вопрос вопрос.

Далее, из того, что я могу понять, вы хотели бы извлечь the $injector и не создавать новый экземпляр. Дело в том, что angular.injector создать новый $injector экземпляр для модулей (приложение), указанных в качестве аргументов. Здесь основной модуль AngularJS (ng) должен быть указан явно. Итак, в этом примере кода:

var injector = angular.injector(['gaad', 'components']);

вы пытались создать новый инжектор из компонентов, определенных в модулях "gaad" и "components" и очевидно $compileProvider не определен в пользовательских модулях. добавлять ng модуль в списке "решит" проблему, создав новый инжектор - то, что вы, вероятно, не хотите, чтобы произошло.

чтобы фактически получить экземпляр инжектора, связанный с запущенным приложением мы можем использовать 2 метода:

  • из AngularJS JavaScript самое простое решение-просто ввести $injector экземпляр: http://docs.angularjs.org/api/angular.injector
  • из-за пределов AngularJS world-call angular.element([DOM element]).injector() где [элемент DOM] является элементом купола, где ng-app была определена (или любой дочерний элемент этого элемента). Более подробная информация здесь:http://docs.angularjs.org/api/angular.element

вот jsFiddle, показывающий 2 метода извлечения инжектора:http://jsfiddle.net/xaQzb/

Пожалуйста, обратите внимание что с помощью $injector непосредственно не очень распространенный сценарий за пределами модульного тестирования. Это может быть полезно для получения услуг AngularJS из-за пределов мира AngularJS. Более подробная информация здесь:вызов угловой JS из устаревшего кода.

похоже, вам также нужно включить ng в инжектор.

var injector = angular.injector(['ng', 'b', 'a']);

от: в AngularJS: инжектор

модуль ng должен быть явно добавлен.

проблема заключается в потоке выполнения кода Angular. Интегрировать на @pkozlowski.ответ opensource и связанные с ним комментарии, обратите внимание, что $injector свойство становится доступным для элементов DOM после выполнения кода модуля, так что при доступе к свойству (как при попытке console.log it) свойство все равно будет undefined.

вы можете решить эту проблему, просто установив тайм-аут 0 для выполнения функции ведения журнала (т. е. без явной задержки миллисекунды необходимы). Этот хак работает, потому что функция ведения журнала будет выполняться, когда стек пуст, то есть когда загрузка Angular закончилась и $injector свойство доступно для элементов DOM.

другое (возможно, лучшее) решение в жаргоне Angular было бы включить ваш $injector-доступ к коду в запустить блок (см. Также связанный API). Элемент $injector смогло после этого легко быть впрыснуто в функцию инициализации как a нормальное обслуживание. Это работает, потому что блоки запуска помещаются в очередь и выполняются асинхронно, когда вся начальная загрузка завершена.

ниже вы можете найти две скрипки, по одной для каждого решения.

0 Timeout jsFiddle

запустить блок jsFiddle

EDIT

кроме того, обычно нет необходимости явно загружать ng модуль. В обычных случаях!--6--> модель уже автоматически загружены, если вы хотите выполнить ручную загрузку кода Angular. Часть документов, упомянутых в одном из ответов, относится (неявно, к сожалению) к процедуре ручной загрузки Angular, когда вам нужно вручную создать инжектор и сообщить ему, какие модули вы хотите загрузить