pattmorter
pattmorter

Reputation: 991

Angular Service Injection

I am working on a trivial task (that I got working) which adds an an .active class to dom elements in a tab nav. Simple. Got it working by following https://stackoverflow.com/a/12306136/2068709.

Reading over the answer provided and comparing their controller to example controllers on angular's website I came across something interesting that I don't quite understand.

On the AngularJS website, $scope and $location (and other services) are injected into the controller along with an anonymous function which defines the controller. But on the answer, the services are not injected, rather they are passed via the anonymous function. Why does this work? Shouldn't the service always be injected?

In terms of an example: Why does this

angular.module('controllers', [])
    .controller('NavigationController', ['$scope', '$location', function($scope, $location) { 
        $scope.isActive = function(route) {
            return route === $location.path();
        };
    }])

and this

angular.module('controllers', [])
    .controller('NavigationController', function($scope, $location) { 
        $scope.isActive = function(route) {
            return route === $location.path();
        };
    })

both work?

This may be trivial but its throwing my brain for a loop that I can't figure out.

Upvotes: 3

Views: 248

Answers (3)

dannyde
dannyde

Reputation: 122

This is how angular handles code minification. by keeping strings intact it can keep mapping vars when they are renamed. if you take a look at the code of the controller https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L48 you'll see that the constructor can accept both function and array.

Upvotes: 0

McGarnagle
McGarnagle

Reputation: 102783

The two examples are equivalent - they just make use of different syntax. The first example uses what they call "inline array annotation" (see here). The purpose of this alternate syntax is just to allow a convenient way to make the injected variable names different than the name of the dependency.

So for example, if you wanted the variable names to be "s" and "l", then you could write:

angular.module('controllers', [])
    .controller('NavigationController', ['$scope', '$location', function(s, l) { 
        s.isActive = function(route) {
            return route === l.path();
        };
    }]);

Upvotes: 4

pedrommuller
pedrommuller

Reputation: 16066

Actually they are injected in both cases, the difference between those two cases is in the first scenario you define and name the dependency this could be useful if you minify your js code and that way you are declaring explicitly the dependency for examply it could be:

angular.module('controllers', [])
    .controller('NavigationController', ['$scope', '$location', function($s, $l) { 
        $s.isActive = function(route) {
            return route === $l.path();
        };
    }])

that way angular will know which dependency to inject on which parameter without looking at the naming for each parameter.

the other case you need to be explicit and declare which dependency you'll inject by setting up the name.

I hope that helps.

Upvotes: 2

Related Questions