повторно відкрити та додати залежності до вже завантаженої програми


89

Чи є спосіб ввести пізню залежність до вже завантаженого кутового модуля? Ось що я маю на увазі:

Скажімо, що у мене є загальнодоступний кутовий додаток, який визначається як:

// in app.js
var App = angular.module("App", []);

І на кожній сторінці:

<html ng-app="App">

Пізніше я знову відкриваю додаток, щоб додати логіку на основі потреб поточної сторінки:

// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

Тепер, кажуть , що один з цих бітів на вимогу логіки також вимагає їх власних залежностей (наприклад ngTouch, ngAnimate, ngResourceі т.д.). Як я можу приєднати їх до базової програми? Здається, це не працює:

// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped

Я розумію, що можу зробити все заздалегідь, тобто -

// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);

Або визначте кожен модуль окремо, а потім впорскуйте все в основний додаток ( див. Тут докладніше ):

// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
  // ...
}])

// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])

Але для цього потрібно щоразу ініціалізувати додаток із залежностями поточної сторінки.

Я вважаю за краще , щоб включити основні app.jsна кожній сторінці і просто ввести необхідні розширення для кожної сторінки ( reports.js, home.js, і т.д.), без необхідності перегляду самонастроювання логіки кожен раз додати або видалити що - небудь.

Чи є спосіб ввести залежності, коли програма вже завантажена? Що вважається ідіоматичним способом (або способами) зробити це? Я схиляюся до останнього рішення, але хотів би побачити, чи можна зробити так, як я описав. Дякую.


Чи можете ви дати мені ваш остаточний робочий код, щоб я подивився?
Мангу Сінгх Раджпурохіт

@ user2393267 ммм, так довго, я навіть не уявляю, чи все ще маю цей код ... Вибачте. Я думаю, що я врешті-решт переглянув дизайн, тому що, як правило, коли мені доводиться перебирати речі, це означає, що я роблю це не правильно ... Однак, якщо ви все-таки твердо вирішили дотримуватися цього підходу, відповідь нижче здається хорошим підказкою .
sa125

Відповіді:


115

Я вирішив це так:

зверніться до програми ще раз:

var app = angular.module('app');

потім підсуньте свої нові вимоги до масиву вимог:

app.requires.push('newDependency');

3
Це працює для мене +1 Я використовував це для множинних залежностей, таких як app.requires.push ('doctorCtrl', 'doctorService');
Амір

8
Це врятувало мою архітектуру.
Saeed Neamati

3
Це не працює для мене. Я додаю залежність динамічно, як описано, але Angular все ще не може знайти службу з доданого модуля.
Слава Фомін II

6
І app.requiresє масивом, тому, якщо ви додаєте кілька залежностей (як у прикладі звітів), ви передаєте їх як окремі аргументи pushметоду: app.requires.push('ui.event', 'ngResource');або якщо ваші додаткові залежності вже є масивом:Array.prototype.push.apply(app.requires, ['ui.event', 'ngResource'])
Червоний горошок

2
Я іноді пропускаю голосування, бо не хочу входити в систему, не цього разу! Дякую!
CularBytes

12

Просто ... Отримайте екземпляр модуля за допомогою геттера таким чином: var app = angular.module ("App");

Потім додайте до колекції "вимагає" наступним чином: app.requires [app.requires.length] = "ngResource";

У всякому разі, це спрацювало для мене. ЩАСТИ!


4
Це спрацювало для мене! У мене питання - чому б не використовувати: app.requires.push ("ngResource")?
Філіпп Мунін

9

Згідно з цією пропозицією у групі Google Angular JS, цієї функції на даний момент не існує. Сподіваємось, основна команда вирішить додати цю функціональність, могла б використовувати її сама.


4
Так, це видається особливо корисним для людей, які не обов’язково хочуть будувати СПА.
регулярний майк

4

Якщо ви хочете додати кілька залежностей одночасно, ви можете передати їх у push наступним чином:

<script>
    var app = angular.module('appName');
    app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>

4

Я усвідомлюю, що це давнє запитання, проте поки що жодної робочої відповіді не надано, тому я вирішив поділитися, як я його вирішив.

Рішення вимагає розгалуження Angular, тому ви більше не можете використовувати CDN. Однак модифікація дуже мала, тому я здивований, чому ця функція не існує в Angular.

Я перейшов за посиланням на групи Google, яке було надано в одній з інших відповідей на це запитання. Там я знайшов такий код, який вирішив проблему:

instanceInjector.loadNewModules = function (mods) {
  forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};

Коли я додав цей код до рядка 4414 у вихідному коді кутового 1.5.0 (всередині createInjectorфункції, перед return instanceInjector;оператором), це дозволило мені додавати залежності після завантаження, як це $injector.loadNewModules(['ngCookies']);.


? Що поганого у відповіді з найбільшою оцінкою (станом на 26.06.2017) ? Схоже, його було надано більше року, перш ніж ви це опублікували; ваша відповідь має якусь перевагу?
Червоний горох,

@TheRedPea Ну, нічого страшного в цьому немає, за винятком того, що це не вирішило моєї проблеми, але ця відповідь зробила
tjespe

І це не спрацювало для вас, оскільки, я здогадуюсь, ви вже завантажили свою програму? Я теж це спостерігав ...
Червоний горох,

2
Прочитавши посилання на повідомлення спільноти Google, я ще більше впевнений, що завантаження є причиною необхідності такого рішення. Голосування за те, що оригінальне запитання про "вже завантажену програму", на яку ніхто інший не звертається (справді, ОП, можливо, помилково виражена),
"Червона горошинка",

1

Починаючи з версії 1.6.7, тепер можна ліниво завантажувати модулі після завантаження програми за допомогою $injector.loadNewModules([modules]). Нижче наведено приклад, взятий з документації AngularJS:

app.factory('loadModule', function($injector) {
   return function loadModule(moduleName, bundleUrl) {
     return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
   };
})

Будь ласка, прочитайте повну документацію про loadNewModules, оскільки навколо нього є деякі проблеми.

Також є дуже хороший зразок програми від omkadiri, який використовує його разом з користувацьким інтерфейсом.

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