重新打开并向已经引导的应用程序添加依赖项

有没有一种方法可以将后期依赖注入到已经引导的角模块中? 我的意思是:

假设我有一个站点范围的角度应用程序,定义如下:

// 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
}])

现在,假设这些按需逻辑之一也需要它们自己的依赖项(如 ngTouchngAnimatengResource等)。如何将它们连接到基本应用程序?这似乎行不通:

// 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.jshome.js等) ,而不必在每次添加或删除某些内容时修改引导逻辑。

当应用程序已经启动时,是否有方法引入依赖关系?什么是被认为是惯用的方法(或方法)做到这一点?我倾向于后一种解决方案,但是想看看我所描述的方法是否也可以实现。谢谢。

19510 次浏览

According to this proposal on the Angular JS google group this functionality does not exist as of this moment. Hopefully the core team decides to add this functionality, could use it myself.

Simple... Get an instance of the module using the getter like this: var app = angular.module("App");

Then add to the "requires" collection like this: app.requires[app.requires.length] = "ngResource";

Anyway, this worked for me. GOOD LUCK!

I solved it like this:

reference the app again:

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

then push your new requirements to the requirements array:

app.requires.push('newDependency');

If you wish to add multiple dependencies at once, you can pass them in push as follows:

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

I realize that this is an old question, however, no working answer has yet been provided, so I decided to share how I solved it.

The solution requires forking Angular, so you can't use CDN anymore. However the modification is very small, so I am surprised why this feature doesn't exist in Angular.

I followed the link to google groups that was provided in one of the other answers to this question. There I found the following code, which solved the issue:

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

When I added this code to line 4414 in the angular 1.5.0 source code (inside the createInjector function, before the return instanceInjector; statement), it enabled me to add dependencies after bootstrapping like this $injector.loadNewModules(['ngCookies']);.

Since version 1.6.7 it is now possible to lazy load modules after the app has been bootstrapped using $injector.loadNewModules([modules]). Below is an example taken from AngularJS documentation:

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

Please read full documentation about loadNewModules as there are some gotchas around it.

There's also a very good sample app by omkadiri using it with ui-router.