web-dev-qa-db-ja.com

既にブートストラップされているアプリケーションを再度開き、依存関係を追加します

すでにブートストラップされているangularモジュールに遅い依存関係を注入する方法はありますか?

サイト全体でangularアプリで、次のように定義されているとします:

// 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など)、何かを追加または削除するたびにブートストラップロジックを修正する必要はありません。

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

89
sa125

私はこのように解決しました:

アプリを再度参照します。

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

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

app.requires.Push('newDependency');
115
AlBaraa Sh

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

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

とにかく、これは私のために働いた。がんばろう!

12
David Donovan

Angular JS google group のこの提案によると、この機能は現時点では存在しません。チームはこの機能を追加することを決定し、自分で使用することができます。

9
Matt Nibecker

これは古い質問であることに気づきましたが、実際の答えはまだ提供されていないため、どのように解決したかを共有することにしました。

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

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

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

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

4
tjespe

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

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

バージョン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で使用します。

1
Denis Pshenov