AngularJS Dependency Injection Components – Annotation & Introspection

Since, we studied about AngularJS API. Here, we will talk about AngularJS Dependency Injection. Moreover, we will learn components, annotations, introspection, and example of dependency injection in AngularJS.

Introduction to AngularJS Dependency Injection

What is AngularJS Dependency Injection?

AngularJS Dependency injection defines, how the various components of the software are dependent on each other. Instead of hard-coding a component within another component, a component is given their own dependencies using dependency injection.

Why Dependency Injection?

  • AngularJS Dependency injections make an application modularize.
  • AngularJS DI makes easier to reuse components of an application.
  • It makes easier to test components of an application.
  • It makes easier to configure components of an application.

Do you know What is AngularJS Modules and how to create it?

Components of Dependency Injection in Angular JS

In the form of dependencies, we can inject this set of AngularJS Dependency Injection components. AngularJS provides a supreme dependency mechanism.

List of some core components which can be injected as a dependency in one another:

  • Value
  • Factory
  • Service
  • Provider
  • Constant

1. Value

Value is an object. It can be a number, string or javascript object. It is used to pass the value to controller, service or factories in config or run phase.

Syntax:

var demo = angular.module("myModule", []);  //define a module  
demo.value("numberAsValue", 101);  //create a value object and pass it a data.   
demo.value("stringAsValue", "tutorial");  
demo.value("objectAsValue", { val1 : 103, val2 : "xyz"} );

value() function is used on module to define values. It consists of two parameters, the first parameter is the name of the value and the second parameter is assigned value. Now, these values can be referenced by their names in factories, services, and controllers.

<! DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">

</head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp">

<div ng-controller="myController">
  <h3> Tutorial Id is:</h3>
  {{ID}}
</div>
<script>

   var sample = angular.module('myApp',[]);
   sample.value("id", 101);
   sample.controller('myController', function($scope,id) {
$scope.ID =id;
});

   </script>
   </body>
</html>

Output:

Tutorial Id is:

101

2. Service

It is like a singleton javascript object. It consists of a set of functions to execute certain tasks. Service() function is used on a module to create services. After creation, it is injected into the controller.

<! DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <title>Event Registration</title>

</head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>


<div ng-app = "serviceApp" ng-controller = "serviceController">
   <p>Result: {{result}}</p>
</div>
<script>
   var t = angular.module("serviceApp", []);

t.service('sum', function(){
   this.addition = function(x,y) {
     return x+y;
    }
 });

t.controller('serviceController', function($scope, sum) {
     $scope.result = sum.addition(5,6);
});
    </script>
    </body>
</html>

Output:
Result: 11

Let’s discuss AngularJS Controller with syntax and example 

Note – Config phase is the phase in which angular JS bootstraps itself.

3. Constant

It is used to pass value at config phase irrespective of the fact that value cannot be passed during the config phase.

4. Provider

In the config phase, factory and service are created by using a provider.

5. Factory

A factory is a function that returns value on demand. It returns value on the basis of the requirement made by service and controller. It uses factory function to process the value and return the output.

AngularJS Dependency Injection example-

<!DOCTYPE html> 
<html> 
  <head> 
     <title>AngularJS Dependency Injection</title> 
</head> 
<body> 
<div ng-app = "myApp" ng-controller = "myController"> 
  <p>Enter a number: <input type = "number" ng-model = "number" /></p> 
  <button ng-click = "square()">Result</button> 
  <p>Result: {{result}}</p> 
</div> 

<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> 
<script> 
  var demo = angular.module("myApp", []); 
  demo.config(function($provide) { 
    $provide.provider('MathService', function() { 
      this.$get = function() { 
         var factory = {}; 
         factory.sum = function(a, b) { 
           return a + b; 
         }  
         return factory; 
       }; 
     }); 
  }); 
  demo.value("defaultInput", 10); 
  demo.factory('MathService', function() { 
    var factory = {}; 
    
     factory.sum = function(a, b) { 
      return a + b; 
    } 
     return factory; 
  }); 
   demo.service('demoService', function(MathService){ 
   this.addition = function(a) { 
      return MathService.sum(a,a); 
    } 
  }); 
    demo.controller('myController', function($scope, 
 demoService, defaultInput) { 
    $scope.number = defaultInput; 
    $scope.result = demoService.addition($scope.number); 

    $scope.addition = function() { 
    $scope.result = demoService.addition($scope.number); 
    } 
 }); 
     </script> 
  </body> 
</html> <!DOCTYPE html>  
<html>  
   <head>  
      <title>AngularJS Dependency Injection</title>  
   </head>  
   <body>  
          
      <div ng-app = "myApp" ng-controller = "myController">  
         <p>Enter a number: <input type = "number" ng-model = "number" /></p>  
         <button ng-click = "square()">Result</button>  
         <p>Result: {{result}}</p>  
      </div>  
        
      <script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>  
        
      <script>  
         var demo = angular.module("myApp", []);  
           
         demo.config(function($provide) {  
            $provide.provider('MathService', function() {  
               this.$get = function() {  
                  var factory = {};  
                    
                  factory.sum = function(a, b) {  
                     return a + b;  
                  }  
                  return factory;  
               };  
            });  
         });  
              
         demo.value("defaultInput", 10);  
           
         demo.factory('MathService', function() {  
            var factory = {};  
              
            factory.sum = function(a, b) {  
               return a + b;  
            }  
            return factory;  
         });  
           
         demo.service('demoService', function(MathService){  
            this.addition = function(a) {  
               return MathService.sum(a,a);  
            }  
         });  
           
         demo.controller('myController', function($scope, demoService, defaultInput) {  
            $scope.number = defaultInput;  
            $scope.result = demoService.addition($scope.number);  
  
            $scope.addition = function() {  
               $scope.result = demoService.addition($scope.number);  
            }  
         });  
          </script>  
      </body>  
</html>

Output:

Enter a Number:10

Result

Result: 20

Recommanded Reading – Directives for AngularJS HTML DOM

AngularJS Dependency Annotation

Some functions like controller, service, and factories are invoked through the injector in AngularJS. Therefore, it is required to annotate these functions, so that injector will be well aware of which function is to be injected.

Angular provides three ways of annotating code. It is provided with a service name.

Types of AngularJS Dependency Annotations

1. Inline Array Annotation

To annotate components in angular, inline array annotation is mostly used.

An example that illustrates registering a controller to a module.

var demoApp = angular.module("myApp", []);
demoApp.controller("MyController", ["$scope", "MyService", function($scope, MyService) {
     $scope.myService = MyService;
}]);

In the above example, an array is used. The elements of an array are the name of dependencies and are of string type followed by a function.

2. $inject Property Annotation

It is an array of dependency names that are being injected in the function. You can use the $inject property only when, it is allowed to rename the function parameter in your code and still to inject the right services.

var demoApp = angular.module("myApp", []);
var MyController = function($scope, MyService) {
    $scope.myService = MyService;
};
MyController.$inject = ["$scope", "MyService"];
demoApp.controller("MyController", MyController);

Since it is an array of dependency names, therefore, synchronization is necessary between the array and the parameters in the function declaration.

How to Impement View in AngularJS?

3. Implicit Annotation

It is the easiest way. But if you are minifying code then you cannot use implicit annotation. Because the name of your service will get change as it will get rename then this service will not be available to that function. The parameters passed inside a function are treated as the name of services.

var demoApp = angular.module("myApp", []);
 
demoApp.controller("MyController", function($scope, MyService) {
    $scope.myService = MyService;
});

In the above code, $scope and MyService are the names of services, which pass as a parameter inside a function(). Inside a controller, these services already injects. Here, we don’t require any synchronization of anything with the parameter pass inside the function because there is no array of names. Therefore, we can rearrange dependencies in the function declaration.

Strict Dependency Injection in AngularJS

We can opt for strict dependency injection in AngularJS by using ng-strict-di directive. It will apply on the same element as ng-app.  When you use strict mode, it will throw an error. When we use service by an implicit annotation.

<!doctype html>
<html ng-app="demoApp" ng-strict-di>
<body>
  Result of 2+2 is: {{2+2}}
  <script src="angular.js"></script>
</body>
</html>

Output:

Result of 2+2: 4

In the below example we are using implicit dependency injection in a service name as willBreak. So when the service named as willBreak is instantiated, an error is thrown by angular JS because of its strict mode.

angular.module('demoApp', [])
.factory('willBreak', function($rootScope) {
  // $rootScope is implicitly injected
})
.run(['willBreak', function(willBreak) {
  // AngularJS will throw an error when this runs
}]);

By providing strictDi: true in the optional config argument, we can use strict dependency injection in manual bootstrapping.

angular.bootstrap(document, ['demoApp'], {
  strictDi: true
})

Introspection

Generally when you declare a function with parameters, it is the responsibility of users to pass the parameter inside the function in appropriate order.

For example : Suppose you are declaring a function details with two parameter id and name.

Function details(id, name)
{
// body of function
}

Then the function is called by passing values in it but in the same order as it is passed in function declaration. It means for the function details you have to first pass id then name while calling that function.

Details (101,’ram’);

Similarly in angular JS when you create components like controller, services you need to declare a function in it. This function contains the elements of angular JS.

angular.module('DemoApp', [])
  .controller('DemoController', ['$scope', '$log', function($scope, $log) {
      $scope.name = "ram";
      $log.debug('logging hey!!');
}]);

Here the component controller receives two parameter name of controller and array of elements. ‘DemoController’ is the name of controller. $scope and $log are the two elements of an array follow by an anonymous function. Function contains the same elements of array passed inside it and also in the same order.

Have a Look – ngmodel in AngularJS

AngularJS Dependency Injection Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport"
content="width=device-width, initial-scale=1, user-scalable=yes">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
  <script>
  angular.module('DiApp', [])
  .controller('DiController', ['$scope', function($scope) {
     $scope.name = "ram";
     $scope.id = 101;
}]);
  </script>
</head>
<body ng-app="DiApp" ng-controller="DiController">

<h1>Details</h1>
{{id}}
{{name}}
</body>
</html>

Output:

Details

101 ram

But in the above example there is a duplication. First you declare a string then you are passing the same string through function. Although we don’t need to do this but if we don’t do so at the time of minify our code may break.

Many times we had seen angular code like this:

angular.module('DemoApp', [])
  .controller('DemoController', function($scope, $log) {
      $scope.name = "ram";
      $log.debug('logging hello');
  });

In this code, there is no duplication. We can pass the same string through function, when there is no array of strings can pass.

This is because of introspection, but the only problem is at the time of minifying of javascript code, the scripts parameter name will also get shorten.

And at the time of function call, angular cannot be able to recognize which function to call. This problem does not arise in case of duplication.

Conclusion

AngularJS Dependency injection is the process of injecting dependent functionality at run time into modules. It helps in achieving reusability of code. Suppose you have a functionality that can use at multiple places in a single application so better to define a central service for it and then inject into different modules of an application as a dependency.

Hope, you liked this AngularJS Dependency Injection. In our next tutorial, we will discuss events in AngularJS.

We would love to hear you in the comment section!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.