Dependency Injection in AngularJS

| | 2 min read

Dependency injection is a concept that allows software components to be built having dependencies without bothering about creation and management of that dependencies. It is a good design pattern allowing to build loosely couples components in software.

Lets take a very simple example from AngularJS context to understand how we use it. Consider that a controller in our app wants to store and retrieve configuration values. And it is supposed to use window.localStorage object normally. Controller code without utilizing dependency injection will be like:


.controller('MyController', function($scope) {
  window.localStorage.setItem('config1', 'some value');
  $scope.config2 = window.localStorage.getItem('config2');
}

Disadvantage with this way of coding is that the controller is strongly coupled with window.local Storage object. What if, on some browser the variable name is different? for example window.localstorage. Then our code will be like:


.controller('MyController', function($scope) {
  var storage = window.localStorage || window.localstorage;
  storage.setItem('config1', 'some value');
  $scope.config2 = storage.getItem('config2');
})

In this way controller would be required to handle construction and managing of its dependencies.

We can make the storage object injected to the controller automatically. First we need to register our injectable dependencies using a module factory methods. There are different types of factory methods available like factory(), directive(), filter() etc. We need to use factory() method to register a service object.


.factory('storage', function() {
  return  window.localStorage || window.localstorage;
})

We have registered our storage service. Now we can inject this service to other android components. Let us inject it to our controller. There are three different ways we can create controller with dependencies.
Here I just show there preferred way, other two ways are not that good and may lead to problems if JS code if minified. So, above controller creation code could be changed to:


.controller('MyController', ['$scope', 'storage', function($scope, storage) {
  storage.setItem('config1', 'some value');
  $scope.config2 = storage.getItem('config2');
}])

Now second parameter to controller() method is an array of strings having controller function as last item. Need to make sure that strings in array and function parameters are same. Now controller will receive storage service object automatically when it is called. Any other components can use this same storage object. The storage object would be initialized only for first time when it is required.

Please fell free to share your thoughts and doubts regarding this here. You may also look into other solved issues related to AngularJS over here.