I was wondering if there was a way to import all the factories I've defined in an AngularJS module into a controller without having to list them all. Say I have a file named foo.js
containing:
angular.module("Foo", [])
.factory("Bar1", function() {...})
.factory("Bar2", function() {...})
.factory("Bar3", function() {...})
.factory("Bar4", function() {...});
Now, in my controller.js
file I have:
angular.module("myApp.controllers", ["Foo"]).
controller("MainCtrl", ["Bar1", "Bar2", "Bar3", "Bar4", function(bar1, bar2, bar3, bar4) {
//do stuff with the various bars
}]);
I was simply wondering if there's any elegant way for the controller, since it already imports the module Foo
, to see all its factories (or providers, or services, or directives as a matter of fact).
I was wondering if there was a way to import all the factories I've defined in an AngularJS module into a controller without having to list them all. Say I have a file named foo.js
containing:
angular.module("Foo", [])
.factory("Bar1", function() {...})
.factory("Bar2", function() {...})
.factory("Bar3", function() {...})
.factory("Bar4", function() {...});
Now, in my controller.js
file I have:
angular.module("myApp.controllers", ["Foo"]).
controller("MainCtrl", ["Bar1", "Bar2", "Bar3", "Bar4", function(bar1, bar2, bar3, bar4) {
//do stuff with the various bars
}]);
I was simply wondering if there's any elegant way for the controller, since it already imports the module Foo
, to see all its factories (or providers, or services, or directives as a matter of fact).
1 Answer
Reset to default 5Yes, it is possible.
You can dynamically load a module an examine its _invokeQueue
field (see https://stackoverflow./a/19412176/646543) in order to retrieve the names of all the factories/controllers/etc defined in a module.
You can then use the $injector
service to actually retrieve the factories.
To demonstrate, I've created a quick proof-of-demo. You should be able to directly copy-and-paste the IntrospectModule
factory into your app to get this functionality.
// Creating some test services
angular.module('test-services', [])
.factory('Bar1', function() {
return { 'stuff': function() { return 'calling bar1' } };
})
.factory('Bar2', function() {
return { 'stuff': function() { return 'calling bar2' } };
});
angular.module('myapp', ['test-services'])
.factory('IntrospectModule', function($injector) {
// This factory will dynamically return all services/controllers/directives/etc
// given the module name.
return function (moduleName) {
var out = {};
angular.module(moduleName)._invokeQueue.forEach(function(item) {
var name = item[2][0];
out[name] = $injector.get(name);
});
return out;
};
})
.controller('MainCtrl', function($scope, IntrospectModule) {
// And now I'm using it
var testServices = IntrospectModule('test-services');
$scope.test = testServices.Bar1.stuff();
});
Here's a working plnkr of the above.
Alternatively, if that feels too hacky, you could try creating a 'posite' factory:
angular.module("test-services", [])
.factory("Bar1", function() {...})
.factory("Bar2", function() {...})
.factory("Bar3", function() {...})
.factory("Bar4", function() {...})
.factory("EveryBar", ["Bar1", "Bar2", "Bar3", "Bar4",
function(bar1, bar2, bar3, bar4) {
return {
'bar1': bar1,
'bar2': bar2,
'bar3': bar3,
'bar4': bar4
};
}]);
Then, inside your controllers, do:
angular.module("myApp.controllers", ["test-services"]).
controller("MainCtrl", ["EveryBar", function(everyBar) {
everyBar.bar1.stuff();
}]);
Obviously, the disadvantage of this approach is that it results in a good deal of redundancy when setting up your services -- we're still manually listing everything.
However, if you need to use the same services multiple times in several different controllers, then creating the posite service would at least allow you avoid having to list a bunch of parameters in every controller.
It's also much more explicit then the first solution, and allows you to cleanly enumerate exactly which services you want rather then mucking around in the internals of Angular, and lets you extend the services, add helper/wrapper functions, etc.