angularjs - ejemplos - ¿Cómo verificar la existencia de un módulo sin que se genere un error?
ng if ejemplos (7)
En Angular 1.2, ngRoute
es un módulo separado, por lo que puede usar otros enrutadores de la comunidad como ui.router
.
Estoy escribiendo un módulo de código abierto que pretende trabajar para múltiples implementaciones de enrutadores diferentes. Entonces, ¿cómo puedo verificar qué enrutador está cargado o existe?
Estoy haciendo lo siguiente dentro de una fábrica en mi módulo, pero no funciona de la manera que espero:
if (angular.module("ngRoute"))
// Do ngRoute-specific stuff.
else if (angular.module("ui.router"))
// Do ui.router-specific stuff.
Se genera un error para cualquier módulo que no esté cargado. Por ejemplo, si la aplicación está utilizando ui.router
, se ui.router
el siguiente error para la comprobación ngRoute
:
Error no detectado: [$ injector: nomod] ¡El módulo ''ngRoute'' no está disponible! O bien escribió mal el nombre del módulo o se olvidó de cargarlo. Si registra un módulo, asegúrese de especificar las dependencias como segundo argumento.
AngularJS 1.6.3 y versiones posteriores tienen una forma de verificar si un módulo está cargado a través del servicio $ inyector.
También se agregó en 1.6.7 la capacidad de cargar nuevos módulos que pueden ser de interés para algunos.
La respuesta original es de fiar. Sin embargo, como alternativa, escribí esto cuando necesitaba "encontrar o crear" los módulos. Hay varios casos de uso, pero en general, no le permite preocuparse por el orden de carga de archivos. Puede poner esto en initialModules.js
... o la parte superior de todos sus archivos de directivas / servicios individuales comienzan con algo como esto. Esta pequeña función funciona como un encanto para mí:
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);
Me gustaría probar el servicio en lugar del módulo en sí.
// In controller
if($injector.has(''$route'')){
}
if($injector.has(''$state'')){
}
// In angular config
if($injector.has(''$routeProvider'')){
}
if($injector.has(''$stateProvider'')){
}
No tengo conocimiento de una forma de verificación sin que se haya generado un error; sin embargo, tenga en cuenta que el problema es que fue un Uncaught Error
no Uncaught Error
, no que se haya lanzado un error. El patrón para capturar tal error es el siguiente.
try { angular.module("ngRoute") } catch(err) { /* failed to require */ }
Si se detecta un error, puede probar el otro módulo, y si no, puede usar el primero.
Si su comportamiento será el mismo para cada módulo, podría hacer algo como lo siguiente, en el que definimos una función que intentará el primero de los nombres de los módulos enumerados y, si se produce un error, pruebe la siguiente opción.
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"]);
Si angular.module
para almacenar los nombres en una matriz, entonces simplemente puedes verificar si la matriz contiene el nombre de tu módulo.
Decora angular.module
Ver la respuesta de @dsfq en SO .
Esto debe suceder después de que se cargue angular, pero antes de comenzar a cargar cualquier módulo angular.
Compruebe su módulo
if(angular.modules.indexOf("ngRoute") > -1) ...
Sin embargo, el problema de cargar o crear automáticamente un módulo podría resolverse mejor con algo como gulp-angular-filesort. Funciona realmente impecable.
Desde la página gulp-angular-filesort github: ordene automáticamente los archivos de aplicaciones AngularJS según las definiciones de módulos y el uso
Se usa junto con gulp-inject para inyectar sus archivos de aplicación AngularJS (scripts) en un orden correcto, para deshacerse de todos los errores no detectados: [$ injector: modulerr] .
Descargo de responsabilidad : no estoy afiliado a gulp-angular-filesort, solo lo uso con mucho beneficio.
Una solución mucho mejor es simplemente hacer su comprobación cuando se crea el módulo. Solo necesita una función de utilidad para agregar una devolución de llamada.
//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
}
});