再起動して、すでにブートストラップされたアプリケーションに依存関係を追加します


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

さて、(のようなロジックのものとオンデマンドのビットの1つは、独自の依存関係を必要と言う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私は追加のブートストラップ・ロジック・毎回または削除何かを修正することなく、など)。

アプリが既にブートストラップされているときに依存関係を導入する方法はありますか?これを行う慣用的な方法とは何ですか?私は後者の解決策に傾倒していますが、私が説明した方法も実行できるかどうかを確認したいと思いました。ありがとう。


最終的な作業コードを教えていただけますか?
Mangu Singh Rajpurohit 2015

@ user2393267うーん、長いので、そのコードがまだあるかどうかわかりません...すみません。それでも、このアプローチを追求するために決定されている場合、私は、私は物事を通じてハックする必要がある場合、通常、それは私が右のそれをやっていないよ意味するので、私は最終的には、デザインを再訪だと思う...しかし、以下の答えは良いリードのように思えます。
sa125

回答:


115

私はそれを次のように解決しました:

アプリをもう一度参照します。

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

次に、新しい要件を要件配列にプッシュします。

app.requires.push('newDependency');

3
これは私にとってはうまくいきます+1私はこれをapp.requires.push( 'doctorCtrl'、 'doctorService');のような複数の依存関係に使用しました。
アミール2015年

8
これは私の建築を救った。
Saeed Neamati

3
うまくいきません。説明したように依存関係を動的に追加していますが、Angularは追加されたモジュールからサービスを見つけることができません。
Slava Fomin II

6
そしてapp.requires、配列なので、(レポートの例のように)複数の依存関係を追加する場合は、それらをpushメソッドに個別の引数として渡します。app.requires.push('ui.event', 'ngResource');または、追加の依存関係がすでに配列である場合:Array.prototype.push.apply(app.requires, ['ui.event', 'ngResource'])
Red Pea

2
今回はログインしたくないので、投票をスキップすることがあります。ありがとう!
CularBytes

12

シンプル...次のようなゲッターを使用してモジュールのインスタンスを取得します。var app = angular.module( "App");

次に、次のように「requires」コレクションに追加します。app.requires [app.requires.length] = "ngResource";

とにかく、これは私のために働いた。幸運を!


4
それでうまくいきました!私は質問があります-なぜ使用しないのですか?app.requires.push( "ngResource")?
Philipp Munin 2015年


4

複数の依存関係を一度に追加したい場合は、次のようにそれらをプッシュで渡すことができます。

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

4

これは古い質問だと思いますが、まだ有効な回答が得られていないため、解決方法を共有することにしました。

このソリューションではAngularをフォークする必要があるため、CDNを使用できなくなります。ただし、変更が非常に小さいため、この機能がAngularに存在しない理由に驚いています。

この質問に対する他の回答の1つで提供されたGoogleグループへのリンクをたどりまし。そこで私は問題を解決する次のコードを見つけました:

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

このコードを角度1.5.0のソースコードの4414行目(createInjector関数内、return instanceInjector;ステートメントの前)に追加すると、このようにブートストラップした後、依存関係を追加できます$injector.loadNewModules(['ngCookies']);


最高投票の回答(2017年6月26日現在)の何が問題になっていますか?あなたがこれを投稿する1年以上前に提供されたようです。あなたの答えにはいくつかの利点がありますか?
Red Pea 2017年

@TheRedPeaまあそれは私の問題を解決しなかった以外は何も問題はありませんが、この答えは解決しました
tjespe

そして、それはあなたのために機能しませんでした、なぜなら私は推測しているのですが、あなたはすでにあなたのアプリをブートストラップしましたか?私もそれを観察しました...
レッドピー

2
リンクされたGoogleコミュニティの投稿を読んだ後、ブートストラップがこのようなソリューションが必要な理由であることはさらに確信しています。元の質問が「すでにブートストラップされたアプリケーション」について尋ねたため、賛成票を投じました。これは、他の誰も対処していないためです(実際にOPが間違っている可能性があります)
Red Pea

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がui-routerと一緒に使用する非常に優れたサンプルアプリもあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.