Absolutely, there is a way to achieve this.
You have the option to dynamically load a module and inspect its _invokeQueue
field (refer to ) to fetch the names of all the factories/controllers defined within that module.
Subsequently, you can utilize the $injector
service to actually obtain those factories.
To illustrate, I've devised a quick proof-of-concept. You should be able to directly copy and paste the IntrospectModule
factory into your application in order to access this functionality.
// Example of creating 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) {
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) {
var testServices = IntrospectModule('test-services');
$scope.test = testServices.Bar1.stuff();
});
For demonstration purposes, here's a working plnkr link demonstrating the above implementation.
If the previous method seems too intricate, an alternative approach would involve creating a 'composite' 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, within your controllers, you can do:
angular.module("myApp.controllers", ["test-services"]).
controller("MainCtrl", ["EveryBar", function(everyBar) {
everyBar.bar1.stuff();
}]);
This approach may lead to some redundancy during service setup as we are listing all services manually. However, if you find yourself needing to utilize the same services across multiple controllers, creating a composite service could streamline this process by eliminating the need to list parameters in each controller.
Moreover, this method is more explicit compared to the initial solution, allowing you to clearly specify which services you require without delving into Angular internals. It also gives you the flexibility to extend services, incorporate helper functions, and so forth.