Не удается извлечь инжектор из углового положения
У меня есть это приложение с двумя модулями:
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
Приложение сейчас довольно большое, и я понятия не имею, где искать ошибки. Итак, мой вопрос: что может быть причиной моих проблем?
РЕДАКТИРОВАТЬ: я смог повторить мою проблему: http://jsfiddle.net/selbh/ehmnt/11/
3 ответа
Прежде чем ответить на вопрос, мы должны отметить, что существует только один экземпляр инжектора для приложения, а не для модуля. В этом смысле невозможно извлечь инжектор на модуль. Конечно, если мы возьмем модуль верхнего уровня, он представляет все приложение. В этом смысле приложение и модуль верхнего уровня кажутся эквивалентными. Это может показаться незначительной разницей, но это важно понять, чтобы полностью и правильно ответить на этот вопрос.
Далее, насколько я понимаю, вы хотели бы получить $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 - звоните
angular.element([DOM element]).injector()
где [элемент DOM] является элементом купола, гдеng-app
был определен (или любой дочерний элемент этого элемента). Более подробная информация здесь: http://docs.angularjs.org/api/angular.element
Вот jsFiddle, показывающий 2 метода поиска инжектора: http://jsfiddle.net/xaQzb/
Пожалуйста, обратите внимание, что с помощью $injector
напрямую не очень распространенный сценарий вне юнит-тестирования. Это может быть полезно для извлечения сервисов AngularJS из-за пределов мира AngularJS. Более подробная информация здесь: Позвоните в Angular JS из старого кода.
Похоже, вам нужно включить нг в инжектор.
var injector = angular.injector(['ng', 'b', 'a']);
Модуль ng должен быть явно добавлен.
Проблема в потоке выполнения кода Angular. Чтобы интегрировать ответ @pkozlowski.opensource и соответствующие комментарии, обратите внимание, что $injector
свойство становится доступным для элементов DOM после выполнения кода модуля, чтобы при доступе к свойству (как при попытке console.log
это) собственность все равно будет undefined
,
Вы можете решить эту проблему, просто установив таймаут 0 для выполнения функции регистрации (т. Е. Не требуется явная задержка в миллисекундах). Этот хак работает, потому что функция ведения журнала будет выполняться, когда стек пуст, то есть когда завершится начальная загрузка Angular и $injector
свойство доступно для элементов DOM.
Другое (возможно, лучшее) решение в англоязычном жаргоне будет включать ваш $injector
- доступ к коду в блоке выполнения (см. также соответствующий API). $injector
затем может быть легко введен в функцию инициализации как обычный сервис. Это работает, потому что блоки выполнения ставятся в очередь и выполняются асинхронно, когда завершается вся начальная загрузка.
Ниже вы можете найти две скрипки, по одной для каждого решения.
РЕДАКТИРОВАТЬ
Кроме того, обычно нет необходимости явно загружать ng
модуль. В нормальных случаях ng
Модель уже загружена автоматически, если вы не хотите выполнить ручную загрузку кода Angular. Документ, на который ссылается один из ответов, относится (неявно, к сожалению) к ручной процедуре начальной загрузки Angular, когда вам нужно вручную создать инжектор и сообщить ему, какие модули вы хотите загрузить.