| 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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
 | @ngdoc overview
@name Tutorial: Step 7
@description
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_06 Previous}</td>
<td id="step_result">{@link  http://angular.github.com/angular-phonecat/step-7/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-6...step-7 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_08 Next}</td>
</tr>
</table>
In this step, you will learn how to create a layout template and how to build an app that has
multiple views by adding routing. 
1. Reset your workspace to Step 7 using:
         git checkout --force step-7
  or
         ./goto_step.sh 7
2. Refresh your browser, but be sure that there is nothing in the url after `app/index.html`, or
check the app out on {@link http://angular.github.com/angular-phonecat/step-7/app angular's
server}. Note that you are redirected to `app/index.html#/phones` and the same phone list appears
in the browser. When you click on a phone link the stub of a phone detail page is displayed.
The most important changes are listed below. You can see the full diff on {@link
https://github.com/angular/angular-phonecat/compare/step-6...step-7
GitHub}:
## What's going on here?
Our app is slowly growing and becoming more complex. Before step 7, the app provided our users
with a single view (the list of all phones), and all of the template code was located in the
`index.html` file. The next step in building the app is the addition of a view that will show
detailed information about each of the devices in our list.  
To add the detailed view, we could expand the `index.html` file to contain template code for both
views, but that would get messy very quickly. Instead, we are going to turn the `index.html`
template into what we call a "layout template". This is a template that is common for all views in
our application.   Other "partial templates" are then included into this layout template depending
on the current "route" — the view that is currently displayed to the user.
Application routes in angular are declared via the {@link angular.service.$route $route} service.
This service makes it easy to wire together controllers, view templates, and the current URL
location in the browser. Using this feature we can implement {@link
http://en.wikipedia.org/wiki/Deep_linking deep linking}, which lets us utilize the browser's
history (back and forward navigation) and bookmarks.
## Controllers
__`app/js/controller.js`:__
<pre>
function PhoneCatCtrl($route) {
  var self = this;
  $route.when('/phones',
              {template: 'partials/phone-list.html',   controller: PhoneListCtrl});
  $route.when('/phones/:phoneId',
              {template: 'partials/phone-detail.html', controller: PhoneDetailCtrl});
  $route.otherwise({redirectTo: '/phones'});
  $route.onChange(function(){
    self.params = $route.current.params;
  });
  $route.parent(this);
}
//PhoneCatCtrl.$inject = ['$route'];
...
</pre>
We created a new controller called `PhoneCatCtrl`. We declared its dependency on the `$route`
service and used this service to declare that our application consists of two different views: 
* The phone list view will be shown when the URL hash fragment is `/phone`. To construct this
view, angular will use the `phone-list.html` template and the `PhoneListCtrl` controller.
* The phone details view will be shown when the URL hash fragment matches '/phone/[phoneId]'. To
construct this view, angular will use the `phone-detail.html` template and the `PhoneDetailCtrl`
controller.
We reused the `PhoneListCtrl` controller for the first view and we added an empty
`PhoneDetailCtrl` controller to the `app/js/controllers.js` file for the second one.
The statement `$route.otherwise({redirectTo: '/phones'})` triggers a redirection to `/phones` when
the browser address doesn't match either of our routes.
Thanks to the `$route.parent(this);` statement and `ng:controller="PhoneCatCtrl"` declaration in
the `index.html` template, the `PhoneCatCtrl` controller has a special role in our app. It is the
"root" controller or the parent controller for the other two sub-controllers (`PhoneListCtrl` and
`PhoneDetailCtrl`). The sub-controllers inherit the model properties and behavior from the root
controller.
Note the use of the `:phoneId` parameter in the second route declaration (`'/phones/:phoneId'`).
When the current URL matches this route, the `$route` service extracts the `phoneId` string from
the current URL and provides it to our controller via the `$route.current.params` map. We will use
the `phoneId` parameter in the `phone-details.html` template thanks to the alias created in the
{@link angular.service.$route `$route.onChange`} callback.
        
In this `onChange` callback, we aliased url parameters extracted from the current route to the
`params` property in the root scope. This model property is inherited by child scopes created for
our routes and accessible by their controllers and templates, just like the `phone-list.html`
template demonstrates.
## Template
The `$route` service is usually used in conjunction with the {@link angular.widget.ng:view
ng:view} widget. The role of the `ng:view` widget is to include the view template for the current
route into the layout template, which makes it a perfect fit for our `index.html` template.
__`app/index.html`:__
<pre>
...
<body ng:controller="PhoneCatCtrl">
  <ng:view></ng:view>
  <script src="lib/angular/angular.js" ng:autobind></script>
  <script src="js/controllers.js"></script>
</body>
</html>
</pre>
Note that we removed most of the code in the `index.html` template and replaced it with a single
line containing the `ng:view` tag. The code that we removed was placed into the `phone-list.html`
template:
__`app/partials/phone-list.html`:__
<pre>
<ul class="predicates">
  <li>
    Search: <input type="text" name="query"/>
  </li>
  <li>
    Sort by:
    <select name="orderProp">
      <option value="name">Alphabetical</option>
      <option value="age">Newest</option>
    </select>
  </li>
</ul>
<ul class="phones">
  <li ng:repeat="phone in phones.$filter(query).$orderBy(orderProp)">
    <a href="#/phones/{{phone.id}}">{{phone.name}}</a>
    <a href="#/phones/{{phone.id}}" class="thumb"><img ng:src="{{phone.imageUrl}}"></a>
    <p>{{phone.snippet}}</p>
  </li>
</ul>
</pre>
We also added a placeholder template for the phone details view:
__`app/partials/phone-list.html`:__
<pre>
TBD: detail view for {{params.phoneId}}
</pre>
Note how we are using `params` model defined in the `PhoneCanCtrl` controller.
## Test
To automatically verify that everything is wired properly, we wrote end-to-end tests that navigate
to various URLs and verify that the correct view was rendered.
<pre>
...
  it('should redirect index.html to index.html#/phones', function() {
   browser().navigateTo('../../app/index.html');
   expect(browser().location().hash()).toBe('/phones');
  });
...
 describe('Phone detail view', function() {
   beforeEach(function() {
      browser().navigateTo('../../app/index.html#/phones/nexus-s');
   });
   it('should display placeholder page with phoneId', function() {
      expect(binding('params.phoneId')).toBe('nexus-s');
   });
 });
</pre>
You can now refresh the browser tab with the end-to-end test runner to see the tests run, or you
can see them running on {@link
http://angular.github.com/angular-phonecat/step-7/test/e2e/runner.html
angular's server}.
# Experiments
* Try to add an `{{orderProp}}` binding to `index.html`, and you'll see that nothing happens even
when you are in the phone list view. This is because the `orderProp` model is visible only in the
scope managed by `PhoneListCtrl`, which is associated with the `<ng:view>` element. If you add the
same binding into the `phone-list.html` template, the binding will work as expected.
* In `PhoneCatCtrl`, create a new model called "`firstName`" with `this.hero = 'Zoro'`. In
`PhoneListCtrl` let's shadow it with `this.hero = 'Batman'`, and in `PhoneDetailCtrl` we'll use
`this.hero = "Captain Proton"`. Then add the `<p>hero = {{hero}}</p>` to all three of our
templates (`index.html`, `phone-list.html`, and `phone-detail.html`). Open the app and you'll see
scope inheritance and model property shadowing do some wonders. 
# Summary
With the routing set up and the phone list view implemented, we're ready to go to step 8 to
implement the phone details view.
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_06 Previous}</td>
<td id="step_result">{@link  http://angular.github.com/angular-phonecat/step-7/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-6...step-7 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_08 Next}</td>
</tr>
</table>
 |