JesusTheHun
JesusTheHun

Reputation: 1237

AngularJS dynamic dependency injection

I am setting up a system of driver for my storage provider.

I have a very basic storage provider :

angular.module('mooseGarden').provider('storage', function () {

    var storage = this;
    var driverName;

    this.setDriverName = function(name) {
        driverName = name;
        return storage;
    };

    this.getDriverName = function() {
        return driverName;
    };

    this.$get = [driverName, function(driver) {

        return {
            set: function(key, value) {
                driver.set(key, value);
            },
            get: function(key) {
                driver.get(key);
            }
        };
    }];
});

Which is configured this way :

app.config(['storageProvider', function(storageProvider) {
    storageProvider.setDriverName('StorageDriver_LocalStorage');
}]);

The StorageDriver_LocalStorage is defined somewhere else in the application.

The provider

You notice the variable driverName which is set as the service to inject. I want the drivers to be services in the Angular application ; beyond the "clean and beautiful" way it brings, I also want those drivers to be importable from others modules and programmatically defined as the driver to use.

What is the problem with this setup ?

The storageProvider is a dependency of the config block. I expected the provider to be loaded like an object / not an angular service, not the $get method to be called. It happens not to be the case, $get is called. The driver service being a dependency of the provider, the app is stuck.

I find this a bit silly because the whole purpose of a provider is that it can be configured before use, yet you cannot get them without instantiation. I think I got confused somewhere...

Does anyone know how to resolve this ?

Upvotes: 3

Views: 1611

Answers (1)

Nate Wagar
Nate Wagar

Reputation: 640

The issue isn't that $get has been executed - it's that Angular has already figured out what dependencies to send to $get.

What you need to use instead is Angular's $injector service (the get method specifically).

var driver = $injector.get(driverName);

I've thrown together a quick Plnkr to demonstrate.

Upvotes: 3

Related Questions