Responsibilities of DI subsystem

Creating components Resolving their dependencies Connecting them with other components as requested

Angular DI style is Construction Injection

Construction Injection Property Injection Setter Injection

var myApp = angular.module('myApp',[]); myApp.service('Auth', function() { this.userName = /* some function to return user name */; }); myApp.controller('GreetingController', ['$scope', 'Auth', function($scope, Auth) { $scope.greeting = 'Hola ' + Auth.userName + '!';

}]);

How does it work?:

// create an injector var $injector = angular.injector(['ng']); // use the injector to kick off your application // use the type inference to auto inject arguments, or use implicit injection. $injector.invoke(function($rootScope, $compile, $document) { $compile($document)($rootScope); $rootScope.$digest(); });

var $div = $(' <div ng-controller="MyCtrl"> {{content.label}}</div>' ); $(document.body).append($div); angular.element(document).injector().invoke(function($compile) { var scope = angular.element($div).scope(); $compile($div)(scope); });

How Injector resolve the dependencies?

Using the inline array annotation (preferred) Using the $inject property annotation Implicitly from the function parameter names

Inline Array Annotation Every component as an ID, and when we register it we pass its dependency IDs as an array.

Code worth 1000 words, and we here list the code to register a module and its controller.

var someModule = angular.module('someModule', []); someModule.controller('MyController', ['$scope', 'greeter', function($scope, greeter) { // .....}]); The Annotations are the string values: '$scope', 'greeter'.

And the IDs are 'someModule', 'MyController'.

The Injector will register a module with the ID : 'someModule', and its controller with ID: 'MyController'.

And it will look for other components with IDs: '$scope' and 'greeter' and inject them in the controller.

This is the safest way to do annotation, the problem with it, is that you have to make sure that the annotation array is in sync with the function parameters, and they are in the exact order.

Any out of sync will make your application go nuts. Using the $inject property annotation $inject property is a property added to an Angular service (or component) which is an array of the annotations.

This is an example of it

var MyController = function($scope, greeter) { //.... }; MyController.$inject = ['$scope', 'greeter']; someModule.controller('MyController', MyController); As you can see the syntax is cleaner with this approach, but we still have to make sure that the annotation array is in sync with the function parameters. Implicit Annotation Implicit annotation means the Injector will get the dependency that has in ID the same as the parameter name.

So the code will be as simple as : var MyController = function($scope, greeter) { //.... }; someModule.controller('MyController', MyController); We don't have to keep track of the parameters to keep them sync with the annotation.

This method is the easiest, except that if we are going to minify our code then it won't work, because minification will minify as well the parameter names.

Using ng-annotate In order to get advantage of the simplicity of implicit annotation, the community came up with a solution for the minification problem.

ng-annotate is a third party tool that will add annotations to your code.

You just write your code like you write using the implicit annotation, which means you don't write any annotations.

And you just mark-up your function which require injection with the "ngInject" directive prologue.

Directive prologue (a well known example of it is "use strict") , are string values which should be written at the beginning of a file, or a function.

We can re-write our previous example as this: var MyController = function($scope, greeter) { "ngInject"; //.... }; someModule.controller('MyController', MyController); ng-annotate tool will parse your code and when it encounters the "ngInject" directive prologue, it will add the $inject property annotation.

Another way to do that is to add /*@ngInject*/ before the function, like this var MyController = /*@ngInject*/ function($scope, greeter) { //.... }; someModule.controller('MyController', MyController); In order to do that we need first to install the tool: npm install -g ng-annotate and then run the tool on our code ng-annotate -a source.js

Using strict mode

<html ng-app="myApp" ng-strict-di> <body> ........ </body> </html>

A typical Angular application contains many modules, each module is a collection of many components (controllers, directives, services, factories, ...).These modules depend on each other, and their components as well depends on other compoenents.Angular solves this dependencies with its Dependency Injection Subsystem.Angular DI subsystem is pervasive throughout Angular and it works with the Module registration process . Whenever we register a new module with its components, the DI will be the registration mechanism to do the following:Assuming you (the reader) know already about DI as a design pattern and the DI frameworks, in other languages like Java or C# the DI frameworks has three flavors:Angular DI is a construction injection style, where we pass dependencies as function arguments.As an example, with this controller code , the controller is depending on : $scope, authService , and as you see we are passing them as arguments.When an Angular application bootstrap, it will create one, and only one " Injector The Injector is a service locator design pattern that will register, find, and couple components together.Angular uses angular.injector function to create the $injector passing all listed modules.This is what Angular run (behind the scene) to generate the injector:If, for any reason you want to access the injector programmatically , you can get it from angular.element. For example , if we are adding dynamic html using jQuery, and want to hook it with the rest of the angular app:Angular style of resolving dependencies uses IDs which are string values to identify components and modules.These IDs are called "Dependency Annotation".There are three types of annotations:If you are defining a new service, but you forgot to add the dependency annotations, then angular will assume that you are planning to use implicit annotation, and that might introduce bugs.For that reason, Angular introduced the "strict mode" in using dependency injection.To use the strict mode, add the directiveinto the same HTML element that has thedirective.This is an example:When you have in your code somewhere that try to use implicit annotations, then it will throw an error.