| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
 | @ngdoc overview
@name Tutorial: Step 5
@description
<table id="tutorial_nav">
<tr>
 <td id="previous_step">{@link tutorial.step_04 Previous}</td>
 <td id="step_result">{@link  http://angular.github.com/angular-phonecat/step-5/app Live Demo
}</td>
 <td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-4...step-5 Code
Diff}</td>
 <td id="next_step">{@link tutorial.step_06 Next}</td>
</tr>
</table>
Enough of building an app with three phones in a hard-coded dataset! Let's fetch a larger dataset
from our server using one of angular's built-in {@link angular.service services} called {@link
angular.service.$xhr $xhr}. We will use angular's dependency injection to provide the service to
the `PhoneListCtrl` controller.
1. Reset your workspace to Step 5 using:
   git checkout --force step-5
or
   ./goto_step.sh 5
2. Refresh your browser or check the app out on {@link
http://angular.github.com/angular-phonecat/step-5/app our server}. You should now see a list of 20
phones.
The most important changes are listed below. You can see the full diff on {@link
https://github.com/angular/angular-phonecat/compare/step-4...step-5
GitHub}:
## Data
The `app/phones/phone.json` file in your project is a dataset that contains a larger list of
phones stored in the JSON format.
Following is a sample of the file:
<pre>
[
 {
  "age": 13,
  "id": "motorola-defy-with-motoblur",
  "name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
  "snippet": "Are you ready for everything life throws your way?"
  ...
 },
...
]
</pre>
## Controller
In this step, the view template will remain the same but the model and controller will change.
We'll use angular's {@link angular.service.$xhr} service to make an HTTP request to your web
server to fetch the data in the `phones.json` file.
__`app/js/controllers.js:`__
<pre>
function PhoneListCtrl($xhr) {
  var self = this;
  $xhr('GET', 'phones/phones.json', function(code, response) {
    self.phones = response;
  });
  self.orderProp = 'age';
}
//PhoneListCtrl.$inject = ['$xhr'];
</pre>
We removed the hard-coded dataset from the controller and instead are using the `$xhr`  service to
access the data stored in `app/phones/phones.json`. The `$xhr` service makes a HTTP GET request to
our web server, asking for `phone/phones.json` (the url is relative to our `index.html` file). The
server responds by providing the data in the json file.
Keep in mind that the response might just as well have been dynamically generated by a backend
server. To the browser and our app they both look the same. For the sake of simplicity we used a
json file in this tutorial. 
Notice that the `$xhr` service takes a callback as the last parameter. This callback is used to
process the response. In our case, we just assign the response to the current scope controlled by
the controller, as a model called `phones`. Have you realized that we didn't even have to parse
the response? Angular took care of that for us.
We already mentioned that the `$xhr` function we just used is an angular service. {@link
angular.service Angular services} are substitutable objects managed by angular's {@link guide.di
DI subsystem}.
Dependency injection helps to make your web apps well structured, loosely coupled, and much easier
to test. What's important to understand is how the controllers get access to these services
through dependency injection.
The dependency injection pattern is based on declaring the dependencies we require and letting the
system provide them to us. To do this in angular, you simply provide the names of the services you
need as arguments to the controller's constructor function, as follows:
    function PhoneListCtrl($xhr) {
The name of the argument is significant, because angular recognizes the identity of a service by
the argument name. Once angular knows what services are being requested, it provides them to the
controller when the controller is being constructed. The dependency injector also takes care of
creating any transitive dependencies the service may have (services often depend upon other
services).
As we mentioned earlier, angular infers the controller's dependencies from the names of arguments
of the controller's constructor function. If you were to minify the JavaScript code for this
controller, all of these function arguments would be minified as well, and the dependency injector
would not being able to identify services correctly. 
To overcome issues caused by minification, just assign an array with service identifier strings
into the `$inject` property of the controller function, just like the last line in the snippet
(commented out) suggests:
    PhoneListCtrl.$inject = ['$xhr'];
## Test
__`test/unit/controllersSpec.js`:__
<pre>
describe('PhoneCat controllers', function() {
  describe('PhoneListCtrl', function(){
    var scope, $browser, ctrl;
    beforeEach(function() {
      scope = angular.scope();
      $browser = scope.$service('$browser');
      $browser.xhr.expectGET('phones/phones.json').respond([{name: 'Nexus S'},
                                                            {name: 'Motorola DROID'}]);
      ctrl = scope.$new(PhoneListCtrl);
    });
    it('should create "phones" model with 2 phones fetched from xhr', function() {
      expect(ctrl.phones).toBeUndefined();
      $browser.xhr.flush();
      expect(ctrl.phones).toEqual([{name: 'Nexus S'},
                                   {name: 'Motorola DROID'}]);
    });
    it('should set the default value of orderProp model', function() {
      expect(ctrl.orderProp).toBe('age');
    });
  });
});
</pre>
Because we started using dependency injection and our controller has dependencies, constructing
the controller in our tests is a bit more complicated. We could use the `new` operator and provide
the constructor with some kind of fake `$xhr` implementation. However, the recommended (and
easier) way is to create a controller in the test environment in the same way that angular does it
in the production code behind the scenes. 
To create the controller in the test environment, do the following:
    * Create a root scope object by calling `angular.scope()`
    * Call `scope.$new(PhoneListCtrl)` to get angular to create the child scope associated with
    the `PhoneListCtrl` controller.
Because our code now uses the `$xhr` service to fetch the phone list data in our controller,
before we create the `PhoneListCtrl` child scope, we need to tell the testing harness to expect an
incoming request from the controller. To do this we:
    * Use the `{@link angular.scope.$service $service}` method to retrieve the `$browser` service,
    a service that angular uses to represent various browser APIs. In tests, angular automatically
    uses a mock version of this service that allows you to write tests without having to deal with
    these native APIs and the global state associated with them.
    * We use the `$browser.expectGET` method to train the `$browser` object to expect an incoming
    HTTP request and tell it what to respond with. Note that the responses are not returned before
    we call the `$browser.xhr.flush()` method.
    * We then make assertions to verify that the `phones` model doesn't exist on the scope, before
    the response is received.
    * We flush the xhr queue in the browser by calling `$browser.xhr.flush()`. This causes the
    callback we passed into the `$xhr` service to be executed with the trained response.
    * Finally, we make the assertions, verifying that the phone model now exists on the scope.
To run the unit tests, execute the `./scripts/test.sh` script and you should see the following
output.
   Chrome: Runner reset.
   ..
   Total 2 tests (Passed: 2; Fails: 0; Errors: 0) (3.00 ms)
     Chrome 11.0.696.57 Mac OS: Run 2 tests (Passed: 2; Fails: 0; Errors 0) (3.00 ms)
Now that you have learned how easy it is to use angular services (thanks to angular's
implementation of dependency injection), go to Step 6, where you will add some thumbnail images of
phones and some links.
<table id="tutorial_nav">
<tr>
 <td id="previous_step">{@link tutorial.step_04 Previous}</td>
 <td id="step_result">{@link  http://angular.github.com/angular-phonecat/step-5/app Live Demo
}</td>
 <td id="tut_home">{@link tutorial Tutorial Home}</td>
 <td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-4...step-5
 Code Diff}</td>
 <td id="next_step">{@link tutorial.step_06 Next}</td>
</tr>
</table>
 |