Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit f9a7b06

Browse files
committedApr 4, 2014
docs(tutorial): synchronize with angular-phonecat changes
1 parent 26ca443 commit f9a7b06

12 files changed

+356
-283
lines changed
 

‎docs/content/tutorial/step_01.ngdoc

+2-5
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@ dynamically display the same result with any set of data.
1212

1313
In this step you will add some basic information about two cell phones to an HTML page.
1414

15+
- The page now contains a list with information about two phones.
1516

1617
<div doc-tutorial-reset="1"></div>
1718

1819

19-
The page now contains a list with information about two phones.
20-
21-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-0...step-1):
22-
23-
__`app/index.html`:__
20+
**`app/index.html`:**
2421

2522
```html
2623
<ul>

‎docs/content/tutorial/step_02.ngdoc

+66-65
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,16 @@
99
Now it's time to make the web page dynamic — with AngularJS. We'll also add a test that verifies the
1010
code for the controller we are going to add.
1111

12-
There are many ways to structure the code for an application. For Angular apps, we encourage the
13-
use of [the Model-View-Controller (MVC)
14-
design pattern](http://en.wikipedia.org/wiki/Model–View–Controller) to decouple the code and to separate concerns. With that in mind, let's use a
15-
little Angular and JavaScript to add model, view, and controller components to our app.
12+
There are many ways to structure the code for an application. For Angular apps, we encourage the use of
13+
[the Model-View-Controller (MVC) design pattern](http://en.wikipedia.org/wiki/Model–View–Controller)
14+
to decouple the code and to separate concerns. With that in mind, let's use a little Angular and
15+
JavaScript to add model, view, and controller components to our app.
1616

17+
- The list of three phones is now generated dynamically from data
1718

1819
<div doc-tutorial-reset="2"></div>
1920

2021

21-
The app now contains a list with three phones.
22-
23-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-1...step-2):
24-
25-
2622
## View and Template
2723

2824
In Angular, the __view__ is a projection of the model through the HTML __template__. This means that
@@ -37,7 +33,7 @@ __`app/index.html`:__
3733
<html ng-app="phonecatApp">
3834
<head>
3935
...
40-
<script src="lib/angular/angular.js"></script>
36+
<script src="../bower_components/angular/angular.js"></script>
4137
<script src="js/controllers.js"></script>
4238
</head>
4339
<body ng-controller="PhoneListCtrl">
@@ -53,21 +49,21 @@ __`app/index.html`:__
5349
</html>
5450
```
5551

56-
We replaced the hard-coded phone list with the
57-
{@link ng.directive:ngRepeat ngRepeat directive} and two
58-
{@link guide/expression Angular expressions} enclosed in curly braces:
59-
`{{phone.name}}` and `{{phone.snippet}}`:
52+
We replaced the hard-coded phone list with the {@link ng.directive:ngRepeat ngRepeat directive}
53+
and two {@link guide/expression Angular expressions}:
6054

61-
* The `ng-repeat="phone in phones"` statement in the `<li>` tag is an Angular repeater. The
62-
repeater tells Angular to create a `<li>` element for each phone in the list using the first `<li>`
55+
* The `ng-repeat="phone in phones"` attribute in the `<li>` tag is an Angular repeater directive.
56+
The repeater tells Angular to create a `<li>` element for each phone in the list using the `<li>`
6357
tag as the template.
58+
* The expressions wrapped in curly braces (`{{phone.name}}` and `{{phone.snippet}}`) will be replaced
59+
by the value of the expressions.
6460

6561
We have added a new directive, called `ng-controller`, which attaches a `PhoneListCtrl`
66-
__controller__ to the DOM at this point.
62+
__controller__ to the DOM at this point:
6763

68-
* As we've learned in {@link step_00 step 0}, the curly braces around `phone.name` and `phone.snippet` denote
69-
bindings. As opposed to evaluating constants, these expressions are referring to our application
70-
model, which was set up in our `PhoneListCtrl` controller.
64+
* The expressions in curly braces (`{{phone.name}}` and `{{phone.snippet}}` denote
65+
bindings, which are referring to our application model, which is set up in our `PhoneListCtrl`
66+
controller.
7167

7268
<img class="diagram" src="img/tutorial/tutorial_02.png">
7369

@@ -128,23 +124,19 @@ To learn more about Angular scopes, see the {@link ng.$rootScope.Scope angular s
128124
## Tests
129125

130126
The "Angular way" of separating controller from the view, makes it easy to test code as it is being
131-
developed. If our controller is available on the global namespace then we can simply instantiate it
132-
with a mock `scope` object. Take a look at the following unit test for our controller:
133-
134-
__`test/unit/controllersSpec.js`:__
127+
developed. If our controller is available on the global namespace then we could simply instantiate it
128+
with a mock `scope` object:
135129

136130
```js
137-
describe('PhoneCat controllers', function() {
131+
describe('PhoneListCtrl', function(){
138132

139-
describe('PhoneListCtrl', function(){
133+
it('should create "phones" model with 3 phones', function() {
134+
var scope = {},
135+
ctrl = new PhoneListCtrl(scope);
140136

141-
it('should create "phones" model with 3 phones', function() {
142-
var scope = {},
143-
ctrl = new PhoneListCtrl(scope);
144-
145-
expect(scope.phones.length).toBe(3);
146-
});
137+
expect(scope.phones.length).toBe(3);
147138
});
139+
148140
});
149141
```
150142

@@ -154,67 +146,72 @@ Angular. Since testing is such a critical part of software development, we make
154146
tests in Angular so that developers are encouraged to write them.
155147

156148
### Testing non-Global Controllers
157-
In practice, you will not want to have your controller functions in the global namespace. Instead,
158-
we have registered our controllers in the `phonecatApp` module. In this case Angular provides a
159-
service, `$controller`, which will retrieve your controller by name. Here is the same test using
160-
`$controller`:
149+
150+
In practice, you will not want to have your controller functions in the global namespace. Instead,
151+
you can see that we have registered it via an anonymous constructor function on the `phoneCatApp`
152+
module.
153+
154+
In this case Angular provides a service, `$controller`, which will retrieve your controller by name.
155+
Here is the same test using `$controller`:
161156

162157
__`test/unit/controllersSpec.js`:__
163158

164159
```js
165-
describe('PhoneCat controllers', function() {
160+
describe('PhoneListCtrl', function(){
161+
166162
beforeEach(module('phonecatApp'));
167163

168-
describe('PhoneListCtrl', function(){
164+
it('should create "phones" model with 3 phones', inject(function($controller) {
165+
var scope = {},
166+
ctrl = $controller('PhoneListCtrl', {$scope:scope});
169167

170-
it('should create "phones" model with 3 phones', inject(function($controller) {
171-
var scope = {},
172-
ctrl = $controller('PhoneListCtrl', { $scope: scope });
168+
expect(scope.phones.length).toBe(3);
169+
}));
173170

174-
expect(scope.phones.length).toBe(3);
175-
}));
176-
});
177171
});
178172
```
179173

180-
Don't forget that we need to load up the `phonecatApp` module into the test so that the controller
181-
is available to be injected.
174+
* Before each test we tell Angular to load the `phonecatApp` module.
175+
* We ask Angular to `inject` the `$controller` service into our test function
176+
* We use `$controller` to create an instance of the `PhoneListCtrl`
177+
* With this instance, we verify that the phones array property on the scope contains three records.
178+
182179

183180
### Writing and Running Tests
181+
184182
Angular developers prefer the syntax of Jasmine's Behavior-driven Development (BDD) framework when
185183
writing tests. Although Angular does not require you to use Jasmine, we wrote all of the tests in
186-
this tutorial in Jasmine. You can learn about Jasmine on the [Jasmine home page](http://jasmine.github.io/) and at the [Jasmine docs](http://jasmine.github.io/).
187-
188-
The angular-seed project is pre-configured to run all unit tests using [Karma](http://karma-runner.github.io/). Ensure that the necessary karma plugins are installed.
189-
You can do this by issuing `npm install` into your terminal.
184+
this tutorial in Jasmine v1.3. You can learn about Jasmine on the [Jasmine home page][jasmine] and
185+
at the [Jasmine docs][jasmine-docs].
190186

187+
The angular-seed project is pre-configured to run unit tests using [Karma][karma] but you will need
188+
to ensure that Karma and its necessary plugins are installed. You can do this by running
189+
`npm install`.
191190

192-
To run the test, do the following:
191+
To run the tests, and then watch the files for changes: `npm test`.
193192

194-
1. In a _separate_ terminal window or tab, go to the `angular-phonecat` directory and run
195-
`npm test` to start the Karma server (the config file necessary to start the server is
196-
located at `./test/karma.conf.js`).
197-
198-
2. Karma will start a new instance of Chrome browser automatically. Just ignore it and let it run in
193+
* Karma will start a new instance of Chrome browser automatically. Just ignore it and let it run in
199194
the background. Karma will use this browser for test execution.
195+
* You should see the following or similar output in the terminal:
200196

201-
3. You should see the following or similar output in the terminal:
202-
203-
info: Karma server started at http://localhost:9876/
204-
info (launcher): Starting browser "Chrome"
205-
info (Chrome 22.0): Connected on socket id tPUm9DXcLHtZTKbAEO-n
206-
Chrome 22.0: Executed 1 of 1 SUCCESS (0.093 secs / 0.004 secs)
197+
<pre>
198+
info: Karma server started at http://localhost:9876/
199+
info (launcher): Starting browser "Chrome"
200+
info (Chrome 22.0): Connected on socket id tPUm9DXcLHtZTKbAEO-n
201+
Chrome 22.0: Executed 1 of 1 SUCCESS (0.093 secs / 0.004 secs)
202+
</pre>
207203

208204
Yay! The test passed! Or not...
209-
210-
4. To rerun the tests, just change any of the source or test .js files. Karma will notice the change
205+
* To rerun the tests, just change any of the source or test .js files. Karma will notice the change
211206
and will rerun the tests for you. Now isn't that sweet?
212207

213208
# Experiments
214209

215210
* Add another binding to `index.html`. For example:
216211

217-
<p>Total number of phones: {{phones.length}}</p>
212+
```html
213+
<p>Total number of phones: {{phones.length}}</p>
214+
```
218215

219216
* Create a new model property in the controller and bind to it from the template. For example:
220217

@@ -255,3 +252,7 @@ to the app.
255252

256253

257254
<ul doc-tutorial-nav="2"></ul>
255+
256+
[jasmine]: http://jasmine.github.io/
257+
[jasmine-docs]: http://jasmine.github.io/1.3/introduction.html
258+
[karma]: http://karma-runner.github.io/

‎docs/content/tutorial/step_03.ngdoc

+14-15
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,10 @@ simple; we will add full text search (yes, it will be simple!). We will also wri
1111
test, because a good end-to-end test is a good friend. It stays with your app, keeps an eye on it,
1212
and quickly detects regressions.
1313

14-
15-
<div doc-tutorial-reset="3"></div>
16-
17-
18-
The app now has a search box. Notice that the phone list on the page changes depending on what a
14+
* The app now has a search box. Notice that the phone list on the page changes depending on what a
1915
user types into the search box.
2016

21-
The most important differences between Steps 2 and 3 are listed below. You can see the full diff on
22-
[GitHub](https://github.com/angular/angular-phonecat/compare/step-2...step-3):
17+
<div doc-tutorial-reset="3"></div>
2318

2419

2520
## Controller
@@ -118,22 +113,26 @@ describe('PhoneCat App', function() {
118113
});
119114
```
120115

116+
This test verifies that the search box and the repeater are correctly wired together. Notice how
117+
easy it is to write end-to-end tests in Angular. Although this example is for a simple test, it
118+
really is that easy to set up any functional, readable, end-to-end test.
119+
120+
### Running End to End Tests with Protractor
121121
Even though the syntax of this test looks very much like our controller unit test written with
122-
Jasmine, the end-to-end test uses APIs of {@link guide/dev_guide.e2e-testing Angular's end-to-end
123-
test runner}.
122+
Jasmine, the end-to-end test uses APIs of [Protractor](https://github.com/angular/protractor). Read
123+
about the Protractor APIs at https://github.com/angular/protractor/blob/master/docs/api.md.
124124

125125
Much like Karma is the test runner for unit tests, we use Protractor to run end-to-end tests.
126126
Try it with `npm run protractor`. End-to-end tests are slow, so unlike with unit tests, Protractor
127127
will exit after the test run and will not automatically rerun the test suite on every file change.
128128
To rerun the test suite, execute `npm run protractor` again.
129129

130-
Note: You must ensure you've installed the protractor and updated webdriver prior to running the
131-
`npm run protractor`. You can do this by issuing `npm install` and `npm run update-webdriver` into
132-
your terminal.
130+
<div class="alert alert-info">
131+
Note: You must ensure you've installed the protractor and updated webdriver prior to running the
132+
`npm run protractor`. You can do this by issuing `npm install` and `npm run update-webdriver` into
133+
your terminal.
134+
</div>
133135

134-
This test verifies that the search box and the repeater are correctly wired together. Notice how
135-
easy it is to write end-to-end tests in Angular. Although this example is for a simple test, it
136-
really is that easy to set up any functional, readable, end-to-end test.
137136

138137
# Experiments
139138

‎docs/content/tutorial/step_04.ngdoc

+4-8
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,11 @@ In this step, you will add a feature to let your users control the order of the
1010
list. The dynamic ordering is implemented by creating a new model property, wiring it together with
1111
the repeater, and letting the data binding magic do the rest of the work.
1212

13-
14-
<div doc-tutorial-reset="4"></div>
13+
* In addition to the search box, the app displays a drop down menu that allows users to control the
14+
order in which the phones are listed.
1515

1616

17-
You should see that in addition to the search box, the app displays a drop down menu that allows
18-
users to control the order in which the phones are listed.
19-
20-
The most important differences between Steps 3 and 4 are listed below. You can see the full diff on
21-
[GitHub](https://github.com/angular/angular-phonecat/compare/step-3...step-4):
17+
<div doc-tutorial-reset="4"></div>
2218

2319

2420
## Template
@@ -143,7 +139,7 @@ shared by all tests in the parent `describe` block.
143139

144140
You should now see the following output in the Karma tab:
145141

146-
Chrome 22.0: Executed 2 of 2 SUCCESS (0.021 secs / 0.001 secs)
142+
<pre>Chrome 22.0: Executed 2 of 2 SUCCESS (0.021 secs / 0.001 secs)</pre>
147143

148144

149145
Let's turn our attention to the end-to-end test.

‎docs/content/tutorial/step_05.ngdoc

+5-8
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@ from our server using one of Angular's built-in {@link guide/services services}
1111
ng.$http $http}. We will use Angular's {@link guide/di dependency
1212
injection (DI)} to provide the service to the `PhoneListCtrl` controller.
1313

14+
* There are now a list of 20 phones, loaded from the server.
1415

1516
<div doc-tutorial-reset="5"></div>
1617

1718

18-
You should now see a list of 20 phones.
19-
20-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-4...step-5):
21-
2219
## Data
2320
The `app/phones/phones.json` file in your project is a dataset that contains a larger list of phones
2421
stored in the JSON format.
@@ -165,9 +162,9 @@ __`test/unit/controllersSpec.js`:__
165162

166163
Because we started using dependency injection and our controller has dependencies, constructing the
167164
controller in our tests is a bit more complicated. We could use the `new` operator and provide the
168-
constructor with some kind of fake `$http` implementation. However, the recommended (and easier) way
169-
is to create a controller in the test environment in the same way that Angular does it in the
170-
production code behind the scenes, as follows:
165+
constructor with some kind of fake `$http` implementation. However, Angular provides a mock `$http`
166+
service that we can use in unit tests. We configure "fake" responses to server requests by calling
167+
methods on a service called $httpBackend:
171168

172169
```js
173170
describe('PhoneCat controllers', function() {
@@ -251,7 +248,7 @@ Finally, we verify that the default value of `orderProp` is set correctly:
251248

252249
You should now see the following output in the Karma tab:
253250

254-
Chrome 22.0: Executed 2 of 2 SUCCESS (0.028 secs / 0.007 secs)
251+
<pre>Chrome 22.0: Executed 2 of 2 SUCCESS (0.028 secs / 0.007 secs)</pre>
255252

256253

257254

‎docs/content/tutorial/step_06.ngdoc

+1-6
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,10 @@ In this step, you will add thumbnail images for the phones in the phone list, an
1010
now, will go nowhere. In subsequent steps you will use the links to display additional information
1111
about the phones in the catalog.
1212

13+
* There are now links and images of the phones in the list.
1314

1415
<div doc-tutorial-reset="6"></div>
1516

16-
17-
You should now see links and images of the phones in the list.
18-
19-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-5...step-6):
20-
21-
2217
## Data
2318

2419
Note that the `phones.json` file contains unique ids and image urls for each of the phones. The

‎docs/content/tutorial/step_07.ngdoc

+140-116
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,49 @@
77

88

99
In this step, you will learn how to create a layout template and how to build an app that has
10-
multiple views by adding routing.
10+
multiple views by adding routing, using an Angular module called 'ngRoute'.
1111

12+
* When you now navigate to `app/index.html`, you are redirected to `app/index.html#/phones`
13+
and the phone list appears in the browser.
14+
* When you click on a phone link the stub of a phone detail page is displayed.
1215

1316
<div doc-tutorial-reset="7"></div>
1417

18+
## Dependencies
19+
20+
The routing functionality added by this step is provided by angular in the `ngRoute` module, which
21+
is distributed separately from the core Angular framework.
22+
23+
We are using [Bower][bower] to install client side dependencies. This step updates the
24+
`bower.json` configuration file to include the new dependency:
25+
26+
```json
27+
{
28+
"name": "angular-seed",
29+
"description": "A starter project for AngularJS",
30+
"version": "0.0.0",
31+
"homepage": "https://github.com/angular/angular-seed",
32+
"license": "MIT",
33+
"private": true,
34+
"dependencies": {
35+
"angular": "1.2.x",
36+
"angular-mocks": "~1.2.15",
37+
"bootstrap": "~3.1.1",
38+
"angular-route": "~1.2.15"
39+
}
40+
}
41+
```
1542

16-
Note that when you now navigate to `app/index.html`, you are redirected to `app/index.html#/phones`
17-
and the same phone list appears in the browser. When you click on a phone link the stub of a phone
18-
detail page is displayed.
43+
The new dependency `"angular-route": "~1.2.15"` tells bower to install a version of the
44+
angular-route component that is compatible with version 1.2.15. We must tell bower to download
45+
and install this dependency.
1946

47+
If you have bower installed globally then you can run `bower install` but for this project we have
48+
preconfigured npm to run bower install for us:
2049

21-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-6...step-7).
50+
```
51+
npm install
52+
```
2253

2354

2455
## Multiple Views, Routing and Layout Template
@@ -34,12 +65,11 @@ template into what we call a "layout template". This is a template that is commo
3465
our application. Other "partial templates" are then included into this layout template depending on
3566
the current "route" — the view that is currently displayed to the user.
3667

37-
Application routes in Angular are declared via the
38-
{@link ngRoute.$routeProvider $routeProvider}, which is the provider of the
39-
{@link ngRoute.$route $route service}. This service makes it easy to wire together
40-
controllers, view templates, and the current
41-
URL location in the browser. Using this feature we can implement [deep linking](http://en.wikipedia.org/wiki/Deep_linking), which lets us utilize the browser's
42-
history (back and forward navigation) and bookmarks.
68+
Application routes in Angular are declared via the {@link ngRoute.$routeProvider $routeProvider},
69+
which is the provider of the {@link ngRoute.$route $route service}. This service makes it easy to
70+
wire together controllers, view templates, and the current URL location in the browser. Using this
71+
feature we can implement [deep linking](http://en.wikipedia.org/wiki/Deep_linking), which lets us
72+
utilize the browser's history (back and forward navigation) and bookmarks.
4373

4474

4575
### A Note About DI, Injector and Providers
@@ -68,6 +98,94 @@ of configuring the injector. As opposed to AMD or require.js modules, Angular mo
6898
solve the problem of script load ordering or lazy script fetching. These goals are totally independent and
6999
both module systems can live side by side and fulfil their goals.
70100

101+
## Template
102+
103+
The `$route` service is usually used in conjunction with the {@link ngRoute.directive:ngView
104+
ngView} directive. The role of the `ngView` directive is to include the view template for the current
105+
route into the layout template. This makes it a perfect fit for our `index.html` template.
106+
107+
<div class="alert alert-info">
108+
**Note:** Starting with AngularJS version 1.2, `ngRoute` is in its own module and must be loaded by
109+
loading the additional `angular-route.js` file, which we download via Bower above.
110+
</div>
111+
112+
__`app/index.html`:__
113+
114+
```html
115+
<!doctype html>
116+
<html lang="en" ng-app="phonecatApp">
117+
<head>
118+
...
119+
<script src="../bower_components/angular/angular.js"></script>
120+
<script src="../bower_components/angular-route/angular-route.js"></script>
121+
<script src="js/app.js"></script>
122+
<script src="js/controllers.js"></script>
123+
</head>
124+
<body>
125+
126+
<div ng-view></div>
127+
128+
</body>
129+
</html>
130+
```
131+
132+
We have added to extra `<script>` tags in our index file to load up extra JavaScript files into our
133+
application:
134+
135+
- `angular-route.js` : defines the `ngRoute` module.
136+
- `controllers.js` : defines a new `phonecatControllers` module.
137+
138+
Note that we removed most of the code in the `index.html` template and replaced it with a single
139+
line containing a div with the `ng-view` attribute. The code that we removed was placed into the
140+
`phone-list.html` template:
141+
142+
__`app/partials/phone-list.html`:__
143+
144+
```html
145+
<div class="container-fluid">
146+
<div class="row-fluid">
147+
<div class="span2">
148+
<!--Sidebar content-->
149+
150+
Search: <input ng-model="query">
151+
Sort by:
152+
<select ng-model="orderProp">
153+
<option value="name">Alphabetical</option>
154+
<option value="age">Newest</option>
155+
</select>
156+
157+
</div>
158+
<div class="span10">
159+
<!--Body content-->
160+
161+
<ul class="phones">
162+
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
163+
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
164+
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
165+
<p>{{phone.snippet}}</p>
166+
</li>
167+
</ul>
168+
169+
</div>
170+
</div>
171+
</div>
172+
```
173+
174+
<div style="display:none">
175+
TODO!
176+
<img class="diagram" src="img/tutorial/tutorial_07_final.png">
177+
</div>
178+
179+
We also added a placeholder template for the phone details view:
180+
181+
__`app/partials/phone-detail.html`:__
182+
183+
```html
184+
TBD: detail view for {{phoneId}}
185+
```
186+
187+
Note how we are using the `phoneId` expression which will be defined in the `PhoneDetailCtrl` controller.
188+
71189
## The App Module
72190

73191
__`app/js/app.js`:__
@@ -95,17 +213,15 @@ phonecatApp.config(['$routeProvider',
95213
}]);
96214
```
97215

98-
In order to configure our application with routes, we need to create a module for our application.
99-
We call this module `phonecatApp`. Notice the second argument passed to `angular.module`:
100-
`['ngRoute', 'phonecatControllers']`. This array lists the modules that `phonecatApp` depends on.
101-
102-
Above, we added `angular-route.js` to `index.html`. That's not all we need to do to be able to use
103-
it, however. We also have to add `ngRoute` as a dependency of our app. To improve the organization
104-
of the app, we're going to move the controllers into their own file (as shown below), and call the
105-
module `phonecatControllers`. By listing these two modules as dependencies of `phonecatApp`, we
106-
can use the directives and services they provide.
216+
Above, we added `angular-route.js` and `controllers.js` to `index.html`. That's not all we need to
217+
do to be able to use their code, however. We also have to add the modules dependencies of our app.
218+
To improve the organization of the app, we've moved the controllers into their own file defining its
219+
own module `phonecatControllers` (as shown below). By listing these two modules as dependencies of
220+
`phonecatApp`, we can use the directives and services they provide. Notice the second argument
221+
passed to `angular.module`, `['ngRoute', 'phonecatControllers']`. This array lists the modules that
222+
`phonecatApp` depends on.
107223

108-
Thus using the `config` API we request the `$routeProvider` to be injected into our config function
224+
Using the `config` API we request the `$routeProvider` to be injected into our config function
109225
and use the {@link ngRoute.$routeProvider#when `$routeProvider.when`} API to define our routes.
110226

111227
Our application routes are defined as follows:
@@ -129,19 +245,6 @@ URL. All variables defined with the `:` notation are extracted into the
129245
{@link ngRoute.$routeParams `$routeParams`} object.
130246

131247

132-
In order for our application to bootstrap with our newly created module we'll also need to specify
133-
the module name as the value of the {@link ng.directive:ngApp ngApp}
134-
directive:
135-
136-
__`app/index.html`:__
137-
138-
```html
139-
<!doctype html>
140-
<html lang="en" ng-app="phonecatApp">
141-
...
142-
```
143-
144-
145248
## Controllers
146249

147250
__`app/js/controllers.js`:__
@@ -170,88 +273,6 @@ you will probably want to create separate modules for each major feature of your
170273

171274
Because our example app is relatively small, we'll add all of our controllers to this module.
172275

173-
## Template
174-
175-
The `$route` service is usually used in conjunction with the {@link ngRoute.directive:ngView
176-
ngView} directive. The role of the `ngView` directive is to include the view template for the current
177-
route into the layout template. This makes it a perfect fit for our `index.html` template.
178-
179-
<div class="alert alert-info">
180-
**Note:** Starting with AngularJS version 1.2, `ngRoute` is in its own module and must be loaded by loading
181-
the `angular-route.js` file distributed with Angular. The easiest way to load the file is to add a `<script>`
182-
tag to your `index.html` file as shown below.
183-
</div>
184-
185-
__`app/index.html`:__
186-
187-
```html
188-
<!doctype html>
189-
<html lang="en" ng-app="phonecatApp">
190-
<head>
191-
...
192-
<script src="lib/angular/angular.js"></script>
193-
<script src="lib/angular/angular-route.js"></script>
194-
<script src="js/app.js"></script>
195-
<script src="js/controllers.js"></script>
196-
</head>
197-
<body>
198-
199-
<div ng-view></div>
200-
201-
</body>
202-
</html>
203-
```
204-
205-
Note that we removed most of the code in the `index.html` template and replaced it with a single
206-
line containing a div with the `ng-view` attribute. The code that we removed was placed into the
207-
`phone-list.html` template:
208-
209-
__`app/partials/phone-list.html`:__
210-
211-
```html
212-
<div class="container-fluid">
213-
<div class="row-fluid">
214-
<div class="span2">
215-
<!--Sidebar content-->
216-
217-
Search: <input ng-model="query">
218-
Sort by:
219-
<select ng-model="orderProp">
220-
<option value="name">Alphabetical</option>
221-
<option value="age">Newest</option>
222-
</select>
223-
224-
</div>
225-
<div class="span10">
226-
<!--Body content-->
227-
228-
<ul class="phones">
229-
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
230-
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
231-
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
232-
<p>{{phone.snippet}}</p>
233-
</li>
234-
</ul>
235-
236-
</div>
237-
</div>
238-
</div>
239-
```
240-
241-
<div style="display:none">
242-
TODO!
243-
<img class="diagram" src="img/tutorial/tutorial_07_final.png">
244-
</div>
245-
246-
We also added a placeholder template for the phone details view:
247-
248-
__`app/partials/phone-detail.html`:__
249-
250-
```html
251-
TBD: detail view for {{phoneId}}
252-
```
253-
254-
Note how we are using `phoneId` model defined in the `PhoneDetailCtrl` controller.
255276

256277

257278
## Test
@@ -307,3 +328,6 @@ step 8} to implement the phone details view.
307328

308329

309330
<ul doc-tutorial-nav="7"></ul>
331+
332+
333+
[bower]: http://bower.io

‎docs/content/tutorial/step_08.ngdoc

+6-9
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,14 @@
99
In this step, you will implement the phone details view, which is displayed when a user clicks on a
1010
phone in the phone list.
1111

12-
13-
<div doc-tutorial-reset="8"></div>
14-
15-
16-
Now when you click on a phone on the list, the phone details page with phone-specific information
12+
* When you click on a phone on the list, the phone details page with phone-specific information
1713
is displayed.
1814

19-
To implement the phone details view we will use {@link ng.$http $http} to fetch
20-
our data, and we'll flesh out the `phone-detail.html` view template.
15+
To implement the phone details view we used {@link ng.$http $http} to fetch our data, and we
16+
fleshed out the `phone-detail.html` view template.
17+
18+
<div doc-tutorial-reset="8"></div>
2119

22-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-7...step-8):
2320

2421
## Data
2522

@@ -153,7 +150,7 @@ __`test/unit/controllersSpec.js`:__
153150

154151
You should now see the following output in the Karma tab:
155152

156-
Chrome 22.0: Executed 3 of 3 SUCCESS (0.039 secs / 0.012 secs)
153+
<pre>Chrome 22.0: Executed 3 of 3 SUCCESS (0.039 secs / 0.012 secs)</pre>
157154

158155

159156
We also added a new end-to-end test that navigates to the Nexus S detail page and verifies that the

‎docs/content/tutorial/step_09.ngdoc

+7-12
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@
55

66
<ul doc-tutorial-nav="9"></ul>
77

8-
98
In this step you will learn how to create your own custom display filter.
109

11-
12-
<div doc-tutorial-reset="9"></div>
13-
14-
15-
Navigate to one of the detail pages.
16-
17-
In the previous step, the details page displayed either "true" or "false" to indicate whether
10+
* In the previous step, the details page displayed either "true" or "false" to indicate whether
1811
certain phone features were present or not. We have used a custom filter to convert those text
1912
strings into glyphs: ✓ for "true", and ✘ for "false". Let's see what the filter code looks like.
2013

21-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-8...step-9):
14+
<div doc-tutorial-reset="9"></div>
2215

2316

2417
## Custom Filter
@@ -118,7 +111,7 @@ access to the filter that we want to test. See {@link angular.mock.inject angul
118111

119112
You should now see the following output in the Karma tab:
120113

121-
Chrome 22.0: Executed 4 of 4 SUCCESS (0.034 secs / 0.012 secs)
114+
<pre>Chrome 22.0: Executed 4 of 4 SUCCESS (0.034 secs / 0.012 secs)</pre>
122115

123116

124117
# Experiments
@@ -131,9 +124,11 @@ following bindings to `index.html`:
131124
* `{{ 1304375948024 | date:"MM/dd/yyyy @ h:mma" }}`
132125

133126
* We can also create a model with an input element, and combine it with a filtered binding. Add
134-
the following to index.html:
127+
the following to index.html:
135128

136-
<input ng-model="userInput"> Uppercased: {{ userInput | uppercase }}
129+
```html
130+
<input ng-model="userInput"> Uppercased: {{ userInput | uppercase }}
131+
```
137132

138133

139134
# Summary

‎docs/content/tutorial/step_10.ngdoc

+2-7
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,11 @@
88

99
In this step, you will add a clickable phone image swapper to the phone details page.
1010

11-
12-
<div doc-tutorial-reset="10"></div>
13-
14-
15-
The phone details view displays one large image of the current phone and several smaller thumbnail
11+
* The phone details view displays one large image of the current phone and several smaller thumbnail
1612
images. It would be great if we could replace the large image with any of the thumbnails just by
1713
clicking on the desired thumbnail image. Let's have a look at how we can do this with Angular.
1814

19-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-9...step-10):
20-
15+
<div doc-tutorial-reset="10"></div>
2116

2217
## Controller
2318

‎docs/content/tutorial/step_11.ngdoc

+55-18
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,72 @@
66
<ul doc-tutorial-nav="11"></ul>
77

88

9-
In this step, you will improve the way our app fetches data.
9+
In this step, you will change the way our app fetches data.
10+
11+
* We defined a custom service that represents a [RESTful][restful] client. Using this client we
12+
can make requests to the server for data in an easier way, without having to deal with the
13+
lower-level {@link ng.$http $http} API, HTTP methods and URLs.
1014

1115

1216
<div doc-tutorial-reset="11"></div>
1317

18+
## Dependencies
19+
20+
The RESTful functionality is provided by Angular in the `ngResource` module, which is distributed
21+
separately from the core Angular framework.
22+
23+
We are using [Bower][bower] to install client side dependencies. This step updates the
24+
`bower.json` configuration file to include the new dependency:
25+
26+
```
27+
{
28+
"name": "angular-seed",
29+
"description": "A starter project for AngularJS",
30+
"version": "0.0.0",
31+
"homepage": "https://github.com/angular/angular-seed",
32+
"license": "MIT",
33+
"private": true,
34+
"dependencies": {
35+
"angular": "1.2.x",
36+
"angular-mocks": "~1.2.15",
37+
"bootstrap": "~3.1.1",
38+
"angular-route": "~1.2.15",
39+
"angular-resource": "~1.2.15"
40+
}
41+
}
42+
```
43+
44+
The new dependency `"angular-resource": "~1.2.15"` tells bower to install a version of the
45+
angular-resource component that is compatible with version 1.2.15. We must tell bower to download
46+
and install this dependency.
1447

15-
The next improvement we will make to our app is to define a custom service that represents a [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) client. Using this client we
16-
can make XHR requests for data in an easier way, without having to deal with the lower-level {@link
17-
ng.$http $http} API, HTTP methods and URLs.
48+
If you have bower installed globally then you can run `bower install` but for this project we have
49+
preconfigured npm to run bower install for us:
1850

19-
The most important changes are listed below. You can see the full diff on [GitHub](https://github.com/angular/angular-phonecat/compare/step-10...step-11):
51+
```
52+
npm install
53+
```
2054

2155

2256
## Template
2357

24-
The custom service is defined in `app/js/services.js` so we need to include this file in our layout
25-
template. Additionally, we also need to load the `angular-resource.js` file, which contains the
26-
{@link api/ngResource ngResource} module and in it the {@link api/ngResource.$resource $resource}
27-
service, that we'll soon use:
58+
Our custom resource service will be defined in `app/js/services.js` so we need to include this file
59+
in our layout template. Additionally, we also need to load the `angular-resource.js` file, which
60+
contains the {@link api/ngResource ngResource} module:
2861

2962
__`app/index.html`.__
3063

3164
```html
3265
...
66+
<script src="../bower_components/angular-resource/angular-resource.js"></script>
3367
<script src="js/services.js"></script>
34-
<script src="lib/angular/angular-resource.js"></script>
3568
...
3669
```
3770

3871
## Service
3972

73+
We create our own service to provide access to the phone data on the server:
74+
4075
__`app/js/services.js`.__
4176

4277
```js
@@ -52,13 +87,12 @@ phonecatServices.factory('Phone', ['$resource',
5287

5388
We used the module API to register a custom service using a factory function. We passed in the name
5489
of the service - 'Phone' - and the factory function. The factory function is similar to a
55-
controller's constructor in that both can declare dependencies via function arguments. The Phone
56-
service declared a dependency on the `$resource` service.
90+
controller's constructor in that both can declare dependencies to be injected via function
91+
arguments. The Phone service declared a dependency on the `$resource` service.
5792

5893
The {@link ngResource.$resource `$resource`} service makes it easy to create a
59-
[RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) client with just a few
60-
lines of code. This client can then be used in our application, instead of the lower-level {@link
61-
ng.$http $http} service.
94+
[RESTful][restful] client with just a few lines of code. This client can then be used in our
95+
application, instead of the lower-level {@link ng.$http $http} service.
6296

6397
__`app/js/app.js`.__
6498

@@ -135,8 +169,8 @@ service correctly.
135169
The {@link ngResource.$resource $resource} service augments the response object
136170
with methods for updating and deleting the resource. If we were to use the standard `toEqual`
137171
matcher, our tests would fail because the test values would not match the responses exactly. To
138-
solve the problem, we use a newly-defined `toEqualData` [Jasmine matcher](https://github.com/pivotal/jasmine/wiki/Matchers). When the
139-
`toEqualData` matcher compares two objects, it takes only object properties into account and
172+
solve the problem, we use a newly-defined `toEqualData` [Jasmine matcher][jasmine-matchers]. When
173+
the `toEqualData` matcher compares two objects, it takes only object properties into account and
140174
ignores methods.
141175

142176

@@ -217,7 +251,7 @@ describe('PhoneCat controllers', function() {
217251

218252
You should now see the following output in the Karma tab:
219253

220-
Chrome 22.0: Executed 4 of 4 SUCCESS (0.038 secs / 0.01 secs)
254+
<pre>Chrome 22.0: Executed 4 of 4 SUCCESS (0.038 secs / 0.01 secs)</pre>
221255

222256

223257
# Summary
@@ -227,3 +261,6 @@ learn how to improve this application with animations.
227261

228262

229263
<ul doc-tutorial-nav="11"></ul>
264+
265+
[restful]: http://en.wikipedia.org/wiki/Representational_State_Transfer
266+
[jasmine-matchers]: https://github.com/pivotal/jasmine/wiki/Matchers

‎docs/content/tutorial/step_12.ngdoc

+54-14
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,57 @@
99
In this final step, we will enhance our phonecat web application by attaching CSS and JavaScript
1010
animations on top of the template code we created before.
1111

12+
* Used the `ngAnimate` to enable animations throughout the application.
13+
* Common `ng` directives automatically trigger hooks for animations to tap into.
14+
* When an animation is found then the animation will run in between the standard DOM operation that
15+
is being issued on the element at the given time (e.g. inserting and removing nodes on
16+
{@link api/ng.directive:ngRepeat `ngRepeat`} or adding and removing classes on
17+
{@link api/ng.directive:ngClass `ngClass`}).
1218

1319
<div doc-tutorial-reset="12"></div>
1420

21+
## Dependencies
1522

16-
Now that everything is set in place for a fully functional web application, we can attach CSS and JavaScript
17-
animations to common directives that are used to render our application. AngularJS comes bundled with an
18-
additional JavaScript file called `angular-animate.js` which, when included into the website and set as
19-
a dependency with the application module, will enable animations throughout the application.
23+
The animation functionality is provided by Angular in the `ngAnimate` module, which is distributed
24+
separately from the core Angular framework. In addition we will use `JQuery` in this project to do
25+
extra JavaScript animations.
2026

21-
Common `ng` directives automatically trigger hooks for animations to tap into. When an animation is found
22-
then the animation will run in between the standard DOM operation that is being issued on the element at
23-
the given time (e.g. inserting and removing nodes on {@link api/ng.directive:ngRepeat `ngRepeat`} or adding
24-
and removing classes on {@link api/ng.directive:ngClass `ngClass`}).
27+
We are using [Bower][bower] to install client side dependencies. This step updates the
28+
`bower.json` configuration file to include the new dependency:
2529

26-
The most important changes are listed below. You can see the full diff on
27-
[GitHub](https://github.com/angular/angular-phonecat/compare/step-11...step-12):
30+
```
31+
{
32+
"name": "angular-seed",
33+
"description": "A starter project for AngularJS",
34+
"version": "0.0.0",
35+
"homepage": "https://github.com/angular/angular-seed",
36+
"license": "MIT",
37+
"private": true,
38+
"dependencies": {
39+
"angular": "1.2.x",
40+
"angular-mocks": "~1.2.15",
41+
"bootstrap": "~3.1.1",
42+
"angular-route": "~1.2.15",
43+
"angular-resource": "~1.2.15",
44+
"jquery": "1.10.2",
45+
"angular-animate": "~1.2.15"
46+
}
47+
}
48+
```
49+
50+
* `"angular-animate": "~1.2.15"` tells bower to install a version of the
51+
angular-animate component that is compatible with version 1.2.15.
52+
* `"jquery": "1.10.2"` tells bower to install the 1.1.2 version of JQuery. Note that this is not an
53+
Angular library, it is the standard JQuery library. We can use bower to install a wide range of 3rd
54+
party libraries.
55+
56+
We must tell bower to download and install these dependencies. If you have bower installed globally
57+
then you can run `bower install` but for this project we have preconfigured npm to run bower install
58+
for us:
59+
60+
```
61+
npm install
62+
```
2863

2964

3065
## How Animations work with `ngAnimate`
@@ -46,17 +81,22 @@ __`app/index.html`.__
4681

4782
```html
4883
...
84+
<!-- for CSS Transitions and/or Keyframe Animations -->
85+
<link rel="stylesheet" href="css/animations.css">
86+
87+
...
88+
4989
<!-- jQuery is used for JavaScript animations (include this before angular.js) -->
50-
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
90+
<script src="../bower_components/jquery/jquery.js"></script>
91+
92+
...
5193

5294
<!-- required module to enable animation support in AngularJS -->
53-
<script src="lib/angular/angular-animate.js"></script>
95+
<script src="../bower_components/angular/angular-animate.js"></script>
5496

5597
<!-- for JavaScript Animations -->
5698
<script src="js/animations.js"></script>
5799

58-
<!-- for CSS Transitions and/or Keyframe Animations -->
59-
<link rel="stylesheet" href="css/animations.css">
60100
...
61101
```
62102

0 commit comments

Comments
 (0)
This repository has been archived.