15

Is it possible to inject scope or controller during running ? or any other advice to dynamically inject services into controller ?

Application.controller('IndexController', function($scope){

    // some actions

    if(someconditions) {
            $scope.$inject = [someServiceName];
            // and here i want to use service methods 
    }

});

Thanks in advance

1
  • The problem is i don't know what kind of service i'll receive after actions happened before. thats why i'm confused, any advice in this case ? Commented Jan 19, 2013 at 15:41

2 Answers 2

62

A service can be dynamically injected (by name) into a controller using the $injector. Being able to inject services via controller arguments is just a convenience that Angular provides. Under the hood, the $injector is used by Angular to retrieve object instances. But we can use the $injector ourselves also.

function MyCtrl($scope, $injector) {
  $scope.doSomething = function(someService) {
    var service = $injector.get(someService)  // someService contains the name of a service
    service.value += 10
}

Fiddle.

Sign up to request clarification or add additional context in comments.

9 Comments

Huh. OK. I stand corrected. But what is the benefit of this (besides not having a mile long arguments list)?
I would caution against over use of the $injector. Having a visible list of dependencies tells me how much work is my controller doing and might force me to split the work
Use case for me is for wrapping REST API. Each 'model' type can return related items of other types, so you need to be able to dynamically select the correct service to represent the REST API relatives.
One huge advantage of this approach is when you have a common public interface between a set of services, where you only need to execute 1 service depending on a condition. Instead of having 100 dependencies just in case you have to execute one of those services, you can inject it by name on the fly
@Shashank, it came up just now when I tried it. If that link doesn't work for you, try jsfiddle.net/vaANv/98
|
4

Following is one use case i came across recently, I was trying to inject the a service "myService" in the Factoy and got the following error.

**Uncaught Error:** *[$injector:cdep] Circular dependency found: $http <- $modal <- myService <- interceptorFactory <- $http <- $templateRequest <- $compile*

[http://errors.angularjs.org/1.3.0/$injector/cdep?p0=%24http%20%3C-%20%24mod%E2%80%A6orFactory%20%3C-%20%24http%20%3C-%20%24templateRequest%20%3C-%20%24compile][1]

To solve this issue, $injector came as life saver

var service = $injector.get('myService') //this will create a dynamic service instance 

and now you can use the service in a similar way you have used other services in your application.

2 Comments

I cannot emphasize enough how good this answer is. The rest of our team and I spent almost a week coming up with various solutions to work around the circular imports/dependencies issue (for a case where it isn't even a logical restriction: factories that return stateless helper functions). Importing $injector and calling e.g. var someImportMakingAngularDizzy = $injector.get('someImportMakingAngularDizzy') solved all of that in about 15 minutes. Thank you!
I am glad, it helped you and your team.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.