You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
To manage the responsibility of dependency creation, each Angular application has an {@link
54
-
angular.injector injector}. The injector is a service locator that is responsible for
53
+
angular.injector injector}. The injector is a
54
+
[service locator](http://en.wikipedia.org/wiki/Service_locator_pattern) that is responsible for
55
55
construction and lookup of dependencies.
56
56
57
57
Here is an example of using the injector service:
58
58
59
59
```js
60
60
// Provide the wiring information in a module
61
-
angular.module('myModule', []).
62
-
63
-
// Teach the injector how to build a 'greeter'
64
-
// Notice that greeter itself is dependent on '$window'
65
-
factory('greeter', function($window) {
66
-
// This is a factory function, and is responsible for
67
-
// creating the 'greet' service.
68
-
return {
69
-
greet: function(text) {
70
-
$window.alert(text);
71
-
}
72
-
};
73
-
});
74
-
75
-
// New injector is created from the module.
76
-
// (This is usually done automatically by angular bootstrap)
77
-
var injector = angular.injector(['myModule', 'ng']);
61
+
var myModule = angular.module('myModule', []);
62
+
```
63
+
64
+
Teach the injector how to build a `greeter` service. Notice that `greeter` is dependent on the
65
+
`$window` service. The `greeter` service is an object that contains a `greet` method.
66
+
67
+
```js
68
+
myModule.factory('greeter', function($window) {
69
+
return {
70
+
greet: function(text) {
71
+
$window.alert(text);
72
+
}
73
+
};
74
+
});
75
+
```
76
+
77
+
Create a new injector that can provide components defined in our `myModule` module and request our
78
+
`greeter` service from the injector. (This is usually done automatically by angular bootstrap).
78
79
79
-
// Request any dependency from the injector
80
+
```js
81
+
var injector = angular.injector(['myModule', 'ng']);
80
82
var greeter = injector.get('greeter');
81
83
```
82
84
83
85
Asking for dependencies solves the issue of hard coding, but it also means that the injector needs
84
-
to be passed throughout the application. Passing the injector breaks the [Law of Demeter](http://en.wikipedia.org/wiki/Law_of_Demeter). To remedy this, we turn the
85
-
dependency lookup responsibility to the injector by declaring the dependencies as in this example:
86
+
to be passed throughout the application. Passing the injector breaks the
87
+
[Law of Demeter](http://en.wikipedia.org/wiki/Law_of_Demeter). To remedy this, we use a declarative
88
+
notation in our HTML templates, to hand the responsibility of creating components over to the
89
+
injector, as in this example:
86
90
87
91
```html
88
-
<!-- Given this HTML -->
89
92
<div ng-controller="MyController">
90
93
<button ng-click="sayHello()">Hello</button>
91
94
</div>
92
95
```
93
96
94
97
```js
95
-
// And this controller definition
96
98
function MyController($scope, greeter) {
97
99
$scope.sayHello = function() {
98
100
greeter.greet('Hello World');
99
101
};
100
102
}
103
+
```
101
104
102
-
// The 'ng-controller' directive does this behind the scenes
105
+
When Angular compiles the HTML, it processes the `ng-controller` directive, which in turn
106
+
asks the injector to create an instance of the controller and its dependencies.
107
+
108
+
```js
103
109
injector.instantiate(MyController);
104
110
```
105
111
106
-
Notice that by having the `ng-controller` instantiate the class, it can satisfy all of the
107
-
dependencies of `MyController` without the controller ever knowing about the injector. This is
108
-
the best outcome. The application code simply asks for the dependencies it needs, without having to
109
-
deal with the injector. This setup does not break the Law of Demeter.
112
+
This is all done behinds the scenes. Notice that by having the `ng-controller` ask the injector to
113
+
instantiate the class, it can satisfy all of the dependencies of `MyController` without the
114
+
controller ever knowing about the injector.
115
+
116
+
This is the best outcome. The application code simply declares the dependencies it needs, without
117
+
having to deal with the injector. This setup does not break the Law of Demeter.
118
+
110
119
111
120
## Dependency Annotation
112
121
113
-
How does the injector know what service needs to be injected?
122
+
**How does the injector know what components need to be injected?**
114
123
115
124
The application developer needs to provide annotation information that the injector uses in order
116
125
to resolve the dependencies. Throughout Angular, certain API functions are invoked using the
117
126
injector, as per the API documentation. The injector needs to know what services to inject into
118
-
the function. Below are three equivalent ways of annotating your code with service name
119
-
information. These can be used interchangeably as you see fit and are equivalent.
127
+
the function. There are three equivalent ways of annotating your code with service name
128
+
information:
120
129
121
-
### Inferring Dependencies
130
+
- Implicitly from the function parameter names
131
+
- Using the `$inject` property annotation
132
+
- Using the inline array annotation
133
+
134
+
These can be used interchangeably as you see fit and are equivalent.
135
+
136
+
### Implicit Dependencies
122
137
123
138
The simplest way to get hold of the dependencies, is to assume that the function parameter names
124
139
are the names of the dependencies.
@@ -134,11 +149,12 @@ function declaration and extracting the parameter names. In the above example `$
134
149
`greeter` are two services which need to be injected into the function.
135
150
136
151
While straightforward, this method will not work with JavaScript minifiers/obfuscators as they
137
-
rename the method parameter names. This makes this way of annotating only useful for [pretotyping](http://www.pretotyping.org/), and demo applications.
152
+
rename the method parameter names. This makes this way of annotating only useful for
153
+
[pretotyping](http://www.pretotyping.org/), and demo applications.
138
154
139
-
### `$inject` Annotation
155
+
### `$inject` Property Annotation
140
156
141
-
To allow the minifers to rename the function parameters and still be able to inject right services
157
+
To allow the minifers to rename the function parameters and still be able to inject right services,
142
158
the function needs to be annotated with the `$inject` property. The `$inject` property is an array
143
159
of service names to inject.
144
160
@@ -149,18 +165,18 @@ var MyController = function(renamed$scope, renamedGreeter) {
149
165
MyController['$inject'] = ['$scope', 'greeter'];
150
166
```
151
167
152
-
In this scenario the ordering of the values in the '$inject' array must match the ordering of the arguments to inject.
153
-
Using above code snippet as an example, '$scope' will be injected into 'renamed$scope' and 'greeter' into 'renamedGreeter'.
154
-
Care must be taken that the `$inject` annotation is kept in sync with the actual arguments in the
155
-
function declaration.
168
+
In this scenario the ordering of the values in the `$inject` array must match the ordering of the
169
+
arguments to inject. Using above code snippet as an example, `$scope` will be injected into
170
+
`renamed$scope` and `greeter` into `renamedGreeter`. Care must be taken that the `$inject`
171
+
annotation is kept in sync with the actual arguments in the function declaration.
156
172
157
173
This method of annotation is useful for controller declarations since it assigns the annotation
158
174
information with the function.
159
175
160
-
### Inline Annotation
176
+
### Inline Array Annotation
161
177
162
178
Sometimes using the `$inject` annotation style is not convenient such as when annotating
163
-
directives.
179
+
directives or services defined inline by a factory function.
0 commit comments