When using DI in this fashion:
var MainController = function MainController($scope) {
//use $scope here
};
MainController.$inject = ["$scope"];
It, work but, when it's used like this:
var MainController = function MainController($injector) {
var $scope = $injector.get("$scope");
};
MainController.$inject = ["$injector"];
This will result in error:
Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope
Here's a plunker with an example that showcases the error, check the comments for an alternative to see that only the scope not custom services are affected by this.
I found this Angular bug where they talk about the controller being instantiated before the child $scope is being created as Tomer Avni answered, so:
$scope
work while the second doesn't? $injector
to inject $scope
?I've replied to you on gitter, but answering here as well as it may help other who have the same issue.
When you give Angular a function to call that has values that will be derived from dependency injection (e.g. a service, a controller, etc.), Angular will:
.$inject
property on the function object which should be an array of dependency names as strings (e.g. ['$scope']
).$inject
is undefined, it will use the parameters of the function definition (which works in most cases, unless you minify your code and the names get mangled).So, in a nutshell, it will look up the names you have specified in the DI container.
$scope
doesn't exist in the DI container, only $rootScope
does. So, if you're accessing the injector directly and asking for an instance of $scope
, you'll get the injection error you've seen here.
In the example where it worked, you're not accessing the injector directly but instead relying on Angular working out how to create your controller. That's a subtle difference, but in this case an important one. Within Angular, when creating the controller instance it will resolve $scope
to the result of calling $rootScope.$new()
(i.e. what you would do when manually instantiating the controller in a unit test).
I hope that explains why your example didn't work.
As for the second question, you could manually get a scope instance by doing something like:
var $scope = $injector.get('$rootScope').$new();
But now we're starting to go down a pretty murky path... It's quite atypical to inject the $injector
directly. I'd avoid that if you can. Is there a reason you need to do this?