admin管理员组

文章数量:1335645

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).

Share Improve this question edited Aug 17, 2014 at 22:14 Braiam 4,49611 gold badges49 silver badges83 bronze badges asked Aug 17, 2014 at 20:41 Andrea AloiAndrea Aloi 9911 gold badge17 silver badges38 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

Yes, 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.

本文标签: javascriptImporting multiple AngularJS module39s factoriesStack Overflow