як вводити залежність в module.config (configFn) в angular


74

У кутовому, можна вводити $routeProviderв configфункції

module.config(function ($routeProvider) {


});

Я хочу вкласти в нього свою послугу, як

module.config(function ($routeProvider, myService) {


});

Я впевнений, що служба визначена належним чином, але вона видає виняток, який говорить про те unknown myService, що подія, коли я ввожу вподобання

module.config(function ($routeProvider, $http) {


});

все ще сказано unknown $http.

Ти знаєш чому?


Ви можете вводити $httpлише для конфігурації, тобто як $httpProvider: docs.angularjs.org/api/ng/provider/$httpProvider
dewd

Відповіді:


95

На сторінці Модулі , розділ "Завантаження модулів та залежності":

Блоки конфігурації - виконуються під час реєстрації постачальника та фази конфігурації. Тільки постачальники та константи можуть бути введені в блоки конфігурації. Це робиться для запобігання випадковому встановленню екземплярів служб до їх повного налаштування.

Запускати блоки - виконується після створення інжектора і використовується для запуску програми. Тільки екземпляри та константи можуть бути введені в блоки запуску. Це робиться для запобігання подальшій конфігурації системи під час роботи програми.

Отже, ви не можете вводити у config () власну службу або вбудовані служби, такі як $ http. Замість цього використовуйте run () .


Дякуємо за відповідь, але чому $ routeProvider можна вводити у функцію config, чи це єдина залежність, яку можна вводити у функцію config? Я сумніваюся.
Фред Янг

2
Як зазначено, будь-який "постачальник" (вбудований в Angular, або ваш власний) або "константа" може бути введений у функцію config (). Ось декілька вихідних кодів Angular, що містять вбудовані провайдери: github.com/angular/angular.js/blob/…
Марк Райкок,

57

У мене недостатньо репутації, щоб залишити коментар, але я хотів додати до відповіді Марка.

Ви можете зареєструвати постачальників самостійно. Вони в основному є об'єктами (або конструкторами) із $getметодом. Коли ви реєструєте постачальника, його стандартну версію можна використовувати як послугу чи завод, але версію постачальника можна використовувати і раніше. Отже, grumpyпостачальник, який зареєстрований як

angular.module('...', [])
    .provider('grumpy', GrumpyProviderObject)

тоді доступна у функції налаштування як

    .config(['grumpyProvider', ..., function (grumpyProvider, ...) { ... }])

і може бути введена в контролери просто як

    .controller('myController', ['grumpy', ..., function (grumpy, ...) { ... }])

grumpyОб'єкт , який вводиться в myControllerце просто результат виконання $getметоду на GrumpyProviderObject. Зверніть увагу, що постачальник, якого ви реєструєте, також може бути звичайним конструктором JavaScript.

Примітка: згідно з коментарем @Problematic, ініціалізація провайдера (виклик до angular.module().provider(…)повинен відбуватися перед тим, як буде доступна функція налаштування.


4
Дякую за це. Варто зазначити, що функція конфігурації повинна надходити після постачальника, щоб її ввести. Можливо, це очевидно, але це мене спокусило!
Проблематично

1
Дякую за це. Тепер я бачу, що сам провайдер повинен бути без постфіксу "Провайдер". Мій конфігуратор шукав ProviderProvider, якого він не зміг знайти.
Етьєн Маре

2
Це також буде працювати з constants, оскільки константи також є постачальниками.
Патрік Гіллерт,

10

Ви можете зробити це так:

(function() {
    'use strict';

    angular.module('name', name).config(config);
    // You can do this:
    config.$inject = ['$routeProvider', 'myService'];

    function config($routeProvider, myService) {
        // Or better to use this, but you need to use ng-annotate:
        /* ngInject */

    }
});

Це кращі практики, описані тут


Чому? Я зробив це нещодавно.
Любимов Роман

1
@DanielKobe .config ('config', config); має бути .config (config);
m1kael

Так, моя помилка, я відредагував відповідь. Я переплутав сервіси з простою конфігурацією. Конфігурації не вводяться, як це роблять служби.
Любимов Роман

Не пробував, але це не повинно працювати. Це лише інший спосіб спробувати ввести службу в конфігураційному розділі. Якщо це працює, це помилка в Angular.
hgoebl

3
Це не повинно працювати, мені цікаво, чому так багато голосів? дивись тутConfiguration blocks: get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.
Саорікідо

5

Ви можете зателефонувати вручну, angular.injectorщоб отримати доступ до служб, які не мають залежностей під час .config()блокування вашої програми. Якщо створена вами служба не має залежностей, які потрібно пройти, тоді ви, ймовірно, можете скористатися цим:

angular.module('myApp').config(function () {
    var myService = angular.injector(['ng']).get('myService');
});

Це працює для інших простих сервісів, таких $httpяк:

angular.module('myApp').config(function () {
    var http = angular.injector(['ng']).get('$http');
});

Примітка: Зазвичай вам не потрібно вводити послуги під час фази налаштування, краще створити постачальника, який дозволяє конфігурувати. Документи кажуть, що ця функціональність доступна для випадків, коли сторонні бібліотеки повинні отримати доступ до інжектора вже запущеної програми Angular.


Я спробував це з $ location, але це не працює. Видає повідомлення про помилку "Невідомий постачальник: $ rootElementProvider".
AndrewR

2
Коли ви телефонуєте $injector.get('serviceName')до служби, яка ще не була інстанційована (як у .config()блоці), інжектор намагається створити інстанцію цієї послуги на місці. Якщо ця служба має якісь залежності, вона видасть помилку, оскільки ці відділи відсутні. На жаль, ви не можете надати залежності під час дзвінка .get(). $location має залежність від $rootElement, тому його не можна завантажити таким чином.
Alex Ross

4

Якщо ви хочете ввести залежність (скажімо, від служби), щоб викликати форму функції у маршрутах (.config), як показано нижче templateProvider.getTemplate ('about')

.state('index.about', {  

    url"/about",  
    templateUrl: templateProvider.getTemplate('about'),  
    controller'AboutCtrl',  
    controllerAs'about',  
    data: {pageTitle'About Us Page'}  

})  

Ви повинні створити Постачальника. Не служба, ані завод.

Ось реальний приклад Постачальника, який генерує шлях до шаблону з імені:

(function ({  

    'use strict';  
    angular  

        .module('mega-app')  

        .provider('template', provider);  

      function provider(CONSTANT{  

        // The provider must include a $get() method This $get() method  
        // will be invoked using $injector.invoke() and can therefore use  
        // dependency-injection.  
       this.$get = function ({  

            return {}  

        };  
       /**  
         * generates template path from it's name  
         *  
         * @param name  
         * @returns {string}  
         */  
       this.getTemplate = function (name{  

            return CONSTANT.TEMPLATES_URL + name + '/' + name + '.html';  
        }  


        /**  
         * generates component path from it's name  
         * @param name  
         * @returns {string}  
         */  
       this.getComponent = function (name{  

            return CONSTANT.COMPONENTS_URL + name + '.html';  
        }  

    };  
})();  

Використання такого Постачальника в маршрутах (.config) буде таким:

(function () {  

    'use strict';  
    angular  

        .module('mega-app')  

        .config(routes);  
   function routes($stateProvider, $urlRouterProvider, templateProvider) {  



       $stateProvider  
            //----------------------------------------------------------------  
            // First State  
            //----------------------------------------------------------------  
            .state('index', {  

                abstract: true,  
                url: "/index",  
                templateUrl: templateProvider.getComponent('content'),  
                controller: 'IndexCtrl',  
                controllerAs: 'index',  
            })  

            //----------------------------------------------------------------  
            // State  
            //----------------------------------------------------------------  
            .state('index.home', {  

                url: "/home",  
                templateUrl: templateProvider.getTemplate('home'),  
                controller: 'HomeCtrl',  
                controllerAs: 'home',  
                data: {pageTitle: 'Home Page'}  

            })  

            //----------------------------------------------------------------  
            // State  
            //----------------------------------------------------------------  
            .state('index.about', {  

                url: "/about",  
                templateUrl: templateProvider.getTemplate('about'),  
                controller: 'AboutCtrl',  
                controllerAs: 'about',  
                data: {pageTitle: 'About Us Page'}  

            })  

        //----------------------------------------------------------------  
        // Default State  
        //----------------------------------------------------------------  
       $urlRouterProvider.otherwise('/index/home');  
    };  
})();  

VIP Примітка:

щоб ін'єктувати провайдера, потрібно постфіксувати його xxxProvider (це ім'я провайдера не слід фіксувати, лише під час ін'єкції в .config).


Я хочу зробити виклик $ http у моїй конфігурації та отримати якийсь файл JSON, який містить мови веб-сайтів, а потім передати їх до конфігурації мови .... всі говорять про $ get, але $ get, здається, не запускається самостійно , чи можете ви надати більше інформації, так що якщо цей постачальник повинен замінити файл конфігурації, він це робить, і якщо у нього є якийсь спосіб зателефонувати $ http та ін. пізніше, зробіть це замість цього?
deadManN

-2

Якщо це може полегшити ситуацію для деяких з вас.

Як пояснюється у цій відповіді , ви можете просто додати Providerсвою службу, а потім отримати доступ до внутрішніх функцій за допомогою $get().

Це може бути не найчистішим рішенням, але воно робить свою справу.

module.config(function ($routeProvider, myServiceProvider) {
 // Call a function hello() on myService.
 myServiceProvider.$get().hello();
});

Uncaught TypeError: $ locationProvider. $ Get не є функцією (…)
Gary

Привіт, ти повинен мати можливість використовувати такий, $locationProviderяк він є. Це вже постачальник. Не потрібно використовувати $get()хак. Мені чогось не вистачає?
Ендрю

У ньому немає .path або чогось іншого, просто. $ Get як Array [6], функція hashPrefix та html5Mode. Я $ ін'єктую '$ locationProvider' у конфігурацію, як $ routeProvider.
Gary

-15

Ви можете спробувати це:

module.config(['$routeProvider', '$http', function ($routeProvider, $http) {}]);

Тільки постачальники та константи допускаються до конфігураційних блоків для введення. Послуги не готові до завершення блоку конфігурації.
Стівен Роджерс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.