AngularJS Dependency Injection
Learn how AngularJS's injector automatically supplies dependencies like $scope, $http, and custom services to your controllers and services by matching parameter names.
What Is Dependency Injection?
Dependency injection means a controller or service does not create the objects it depends on - it simply declares what it needs, as parameters, and AngularJS's built-in injector supplies matching instances at runtime. This keeps components decoupled from how their dependencies are built and makes them far easier to test in isolation.
Example
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<script>
angular.module('diApp', [])
.controller('UserController', function($scope, $http) {
$http.get('/api/users').then(function(response) {
$scope.users = response.data;
});
});
</script>
</body>
</html>How the Injector Matches Parameter Names
When AngularJS instantiates a controller or service, it inspects the names of the function's parameters and looks up a registered provider for each matching name - $scope and $http above are both built-in services the injector recognizes automatically. This name-matching works fine in development, but JavaScript minifiers rename parameters, which breaks the match. The fix is the array-string annotation syntax, which pairs each dependency's string name with the function explicitly.
Example
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<script>
angular.module('diApp', [])
.controller('UserController', ['$scope', '$http', function($scope, $http) {
$http.get('/api/users').then(function(response) {
$scope.users = response.data;
});
}]);
</script>
</body>
</html>Creating and Injecting Custom Services
The injector is not limited to AngularJS's built-in services. Registering a service with angular.module(...).factory('Name', fn) adds 'Name' to the injector's registry, and from then on any controller or service can request it simply by naming it as a parameter - exactly the same mechanism used for $scope and $http.
Example
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<script>
angular.module('diApp', [])
.factory('DataService', ['$http', function($http) {
return {
getProducts: function() {
return $http.get('/api/products').then(function(res) {
return res.data;
});
}
};
}])
.controller('ProductController', ['DataService', function(DataService) {
var vm = this;
DataService.getProducts().then(function(products) {
vm.products = products;
});
}]);
</script>
</body>
</html>- `.factory('Name', fn)` - fn's return value becomes the injectable object; the most common way to register a service.
- `.service('Name', Constructor)` - AngularJS instantiates the constructor with `new`; useful when you prefer a class-like style.
- `.provider('Name', fn)` - the most configurable form, allowing setup during the module's config phase; factory and service are both built on top of provider.
Exercise: AngularJS Dependency Injection
How does a controller typically gain access to a service like $http?