Angular 1.2、ngRoute
は独立したモジュールなので、代わりにui.router
などの他のコミュニティルーターを使用できます。
私は、複数の異なるルーターの実装で機能することを目的としたオープンソースモジュールを書いています。それで、どのルーターがロードされているか、存在するかをどのように確認できますか?
私はモジュール内のファクトリ内で次のことを行っていますが、期待どおりに機能しません:
if (angular.module("ngRoute"))
// Do ngRoute-specific stuff.
else if (angular.module("ui.router"))
// Do ui.router-specific stuff.
ロードされていないモジュールに対してエラーが発生します。たとえば、アプリがui.router
を使用している場合、ngRoute
チェックに対して次のエラーが発生します。
不明なエラー:[$ injector:nomod]モジュール 'ngRoute'は使用できません!モジュール名のつづりを間違えたか、ロードするのを忘れました。モジュールを登録する場合は、2番目の引数として依存関係を指定してください。
エラーが発生することなくチェックする方法を知りません。ただし、問題はUncaught Error
、エラーがスローされたことではありません。このようなエラーをキャッチするパターンは次のとおりです。
try { angular.module("ngRoute") } catch(err) { /* failed to require */ }
エラーがキャッチされた場合は、他のモジュールを試すことができます。そうでない場合は、最初のモジュールを使用できます。
動作が各モジュールで同じ場合は、次のようなことができます。リスト内の最初のモジュール名を試みる関数を定義し、エラーがスローされたら次のオプションを試してください。
var tryModules = function(names) {
// accepts a list of module names and
// attempts to load them, in order.
// if no options remain, throw an error.
if( names.length == 0 ) {
throw new Error("None of the modules could be loaded.");
}
// attempt to load the module into m
var m;
try {
m = angular.module(names[0])
} catch(err) {
m = null;
}
// if it could not be loaded, try the rest of
// the options. if it was, return it.
if( m == null ) return tryModules(names.slice(1));
else return m;
};
tryModules(["ngRoute", "ui.router"]);
モジュール自体の代わりにサービスをテストします。
// In controller
if($injector.has('$route')){
}
if($injector.has('$state')){
}
// In angular config
if($injector.has('$routeProvider')){
}
if($injector.has('$stateProvider')){
}
元の答えは合法です。ただし、代わりに、モジュールを「検索または作成」する必要があるときにこれを作成しました。多くのユースケースがありますが、一般的には、ファイルのロード順序を心配する必要はありません。これをinitialModules.js
...に入れるか、個々のサービス/ディレクティブファイルの先頭をこのようなもので始めることができます。この小さな機能は私にとって魅力的です。
var initialModules = [
{name: 'app.directives', deps: ['ui.mask']},
{name: 'app.services'},
{name: 'app.templates'},
{name: 'app.controllers'}
];
initialModules.forEach(function(moduleDefinition) {
findOrCreateModule(moduleDefinition.name, moduleDefinition.deps);
});
function findOrCreateModule(moduleName, deps) {
deps = deps || [];
try {
angular.module(moduleName);
} catch (error) {
angular.module(moduleName, deps);
}
}
///// OR... in like "myDirective.js"
findOrCreateModule('app.directives').directive('myDirective', myDirectiveFunction);
_angular.module
_を修飾して名前を配列に保存すると、配列にモジュール名が含まれているかどうかを確認できます。
SOに関する@dsfqの回答 を参照してください。
これは、angularがロードされた後、任意のangularモジュールをロードする前に発生する必要があります。
if(angular.modules.indexOf("ngRoute") > -1) ...
はるかに優れたソリューションは、モジュールが作成されたときに単純に確認することです。コールバックを追加するには、ユーティリティ関数が必要です。
//create a utility function to add a callback to object methods
//here we are making it a method of the underscore or lowdash object
//but it could be added to the angular global object or anything else
_.addCallBack = function (obj, originalMethodName, callBackMethod, context){
var fnOriginal = obj[originalMethodName],
outcome;
context = context || obj;
obj[originalMethodName] = function () {
var outcome = fnOriginal.apply(this, arguments);
callBackMethod.apply(this, arguments);
return outcome;
};
};
_.addCallBack(angular, "module", function(sModuleName, asDependencies){
if(_.contains(asDependencies, "ngRoute")){
//your logic here
//just loop through if you don't use underscore or lowdash
}
});
AngularJS 1.6.3以降には、 モジュールがロードされているかどうかを確認する方法 が$ injectorサービス経由であります。
また、1.6.7で追加されたのは 新しいモジュールをロードする機能 です。
ただし、モジュールを自動的にロードまたは作成する問題は、gulp-angular-filesortのようなものによってよりよく解決できます。それは本当に完璧に動作します。
gulp-angular-filesort githubページ:AngularJSアプリファイルをモジュール定義と使用法に応じて自動的にソートします
Gulp-injectと組み合わせて使用して、AngularJSアプリケーションファイル(スクリプト)を正しい順序で挿入し、すべてを削除しますUncaught Error:[$ injector:modulerr]。
免責事項:私はgulp-angular-filesortと提携していませんが、多くの利益を得て使用しています。