| <a href='http://github.com/angular/angular.js/edit/master/docs/content/guide/di.ngdoc' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit"> </i>Improve this doc</a> |
| |
| |
| <h1 id="dependency-injection">Dependency Injection</h1> |
| <p>Dependency Injection (DI) is a software design pattern that deals with how code gets hold of its |
| dependencies.</p> |
| <p>The Angular injector subsystem is in charge of service instantiation, resolution |
| of dependencies, and provision of dependencies to components as requested.</p> |
| <p>For in-depth discussion about DI, see |
| <a href="http://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a> at Wikipedia, |
| <a href="http://martinfowler.com/articles/injection.html">Inversion of Control</a> by Martin Fowler, |
| or read about DI in your favorite software design pattern book.</p> |
| <h2 id="di-in-a-nutshell">DI in a nutshell</h2> |
| <p>There are only three ways an object or a function can get a hold of its dependencies:</p> |
| <ol> |
| <li>The dependency can be created, typically using the <code>new</code> operator.</li> |
| <li>The dependency can be looked up by referring to a global variable.</li> |
| <li>The dependency can be passed in to where it is needed.</li> |
| </ol> |
| <p>The first two options of creating or looking up dependencies are not optimal because they hard |
| code the dependency. This makes it difficult, if not impossible, to modify the dependencies. |
| This is especially problematic in tests, where it is often desirable to provide mock dependencies |
| for test isolation.</p> |
| <p>The third option is the most viable, since it removes the responsibility of locating the |
| dependency from the component. The dependency is simply handed to the component.</p> |
| <pre><code class="lang-js">function SomeClass(greeter) { |
| this.greeter = greeter; |
| } |
| |
| SomeClass.prototype.doSomething = function(name) { |
| this.greeter.greet(name); |
| }</code></pre> |
| <p>In the above example <code>SomeClass</code> is not concerned with locating the <code>greeter</code> dependency, it |
| is simply handed the <code>greeter</code> at runtime.</p> |
| <p>This is desirable, but it puts the responsibility of getting hold of the dependency on the |
| code that constructs <code>SomeClass</code>.</p> |
| <p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-injector.png"></p> |
| <p>To manage the responsibility of dependency creation, each Angular application has an <a href="api/ng/function/angular.injector">injector</a>. The injector is a service locator that is responsible for |
| construction and lookup of dependencies.</p> |
| <p>Here is an example of using the injector service:</p> |
| <pre><code class="lang-js">// Provide the wiring information in a module |
| angular.module('myModule', []). |
| |
| // Teach the injector how to build a 'greeter' |
| // Notice that greeter itself is dependent on '$window' |
| factory('greeter', function($window) { |
| // This is a factory function, and is responsible for |
| // creating the 'greet' service. |
| return { |
| greet: function(text) { |
| $window.alert(text); |
| } |
| }; |
| }); |
| |
| // New injector is created from the module. |
| // (This is usually done automatically by angular bootstrap) |
| var injector = angular.injector(['myModule', 'ng']); |
| |
| // Request any dependency from the injector |
| var greeter = injector.get('greeter');</code></pre> |
| <p>Asking for dependencies solves the issue of hard coding, but it also means that the injector needs |
| to be passed throughout the application. Passing the injector breaks the <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a>. To remedy this, we turn the |
| dependency lookup responsibility to the injector by declaring the dependencies as in this example:</p> |
| <pre><code class="lang-html"><!-- Given this HTML --> |
| <div ng-controller="MyController"> |
| <button ng-click="sayHello()">Hello</button> |
| </div></code></pre> |
| <pre><code class="lang-js">// And this controller definition |
| function MyController($scope, greeter) { |
| $scope.sayHello = function() { |
| greeter.greet('Hello World'); |
| }; |
| } |
| |
| // The 'ng-controller' directive does this behind the scenes |
| injector.instantiate(MyController);</code></pre> |
| <p>Notice that by having the <code>ng-controller</code> instantiate the class, it can satisfy all of the |
| dependencies of <code>MyController</code> without the controller ever knowing about the injector. This is |
| the best outcome. The application code simply asks for the dependencies it needs, without having to |
| deal with the injector. This setup does not break the Law of Demeter.</p> |
| <h2 id="dependency-annotation">Dependency Annotation</h2> |
| <p>How does the injector know what service needs to be injected?</p> |
| <p>The application developer needs to provide annotation information that the injector uses in order |
| to resolve the dependencies. Throughout Angular, certain API functions are invoked using the |
| injector, as per the API documentation. The injector needs to know what services to inject into |
| the function. Below are three equivalent ways of annotating your code with service name |
| information. These can be used interchangeably as you see fit and are equivalent.</p> |
| <h3 id="inferring-dependencies">Inferring Dependencies</h3> |
| <p>The simplest way to get hold of the dependencies, is to assume that the function parameter names |
| are the names of the dependencies.</p> |
| <pre><code class="lang-js">function MyController($scope, greeter) { |
| // ... |
| }</code></pre> |
| <p>Given a function the injector can infer the names of the service to inject by examining the |
| function declaration and extracting the parameter names. In the above example <code>$scope</code>, and |
| <code>greeter</code> are two services which need to be injected into the function.</p> |
| <p>While straightforward, this method will not work with JavaScript minifiers/obfuscators as they |
| rename the method parameter names. This makes this way of annotating only useful for <a href="http://www.pretotyping.org/">pretotyping</a>, and demo applications.</p> |
| <h3 id="-inject-annotation"><code>$inject</code> Annotation</h3> |
| <p>To allow the minifers to rename the function parameters and still be able to inject right services |
| the function needs to be annotated with the <code>$inject</code> property. The <code>$inject</code> property is an array |
| of service names to inject.</p> |
| <pre><code class="lang-js">var MyController = function(renamed$scope, renamedGreeter) { |
| ... |
| } |
| MyController['$inject'] = ['$scope', 'greeter'];</code></pre> |
| <p>In this scenario the ordering of the values in the '$inject' array must match the ordering of the arguments to inject. |
| Using above code snippet as an example, '$scope' will be injected into 'renamed$scope' and 'greeter' into 'renamedGreeter'. |
| Care must be taken that the <code>$inject</code> annotation is kept in sync with the actual arguments in the |
| function declaration.</p> |
| <p>This method of annotation is useful for controller declarations since it assigns the annotation |
| information with the function.</p> |
| <h3 id="inline-annotation">Inline Annotation</h3> |
| <p>Sometimes using the <code>$inject</code> annotation style is not convenient such as when annotating |
| directives.</p> |
| <p>For example:</p> |
| <pre><code class="lang-js">someModule.factory('greeter', function($window) { |
| // ... |
| });</code></pre> |
| <p>Results in code bloat due to needing a temporary variable:</p> |
| <pre><code class="lang-js">var greeterFactory = function(renamed$window) { |
| // ... |
| }; |
| |
| greeterFactory.$inject = ['$window']; |
| |
| someModule.factory('greeter', greeterFactory);</code></pre> |
| <p>For this reason the third annotation style is provided as well.</p> |
| <pre><code class="lang-js">someModule.factory('greeter', ['$window', function(renamed$window) { |
| // ... |
| }]);</code></pre> |
| <p>Keep in mind that all of the annotation styles are equivalent and can be used anywhere in Angular |
| where injection is supported.</p> |
| <h2 id="where-can-i-use-di-">Where can I use DI?</h2> |
| <p>DI is pervasive throughout Angular. You can use it in controllers, services, directives, filters, |
| animations, and <code>run</code> and <code>config</code> blocks.</p> |
| <h3 id="di-in-controllers">DI in controllers</h3> |
| <p>Controllers are classes which are responsible for application behavior. The recommended way of |
| declaring controllers is using the array notation:</p> |
| <pre><code class="lang-js">someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) { |
| ... |
| $scope.aMethod = function() { |
| ... |
| } |
| ... |
| }]);</code></pre> |
| <p>This avoids the creation of global functions for controllers and also protects against minification.</p> |
| <h3 id="factory-methods">Factory methods</h3> |
| <p>Factory methods are responsible for creating most objects in Angular. Examples are directives, |
| services, and filters. The factory methods are registered with the module, and the recommended way |
| of declaring factories is:</p> |
| <pre><code class="lang-js">angular.module('myModule', []). |
| config(['depProvider', function(depProvider){ |
| ... |
| }]). |
| factory('serviceId', ['depService', function(depService) { |
| ... |
| }]). |
| directive('directiveName', ['depService', function(depService) { |
| ... |
| }]). |
| filter('filterName', ['depService', function(depService) { |
| ... |
| }]). |
| run(['depService', function(depService) { |
| ... |
| }]);</code></pre> |
| |
| |