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
|
@workInProgress
@ngdoc overview
@name Tutorial: Step 7
@description
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_6 Previous}</td>
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-7/app Example}</td>
<td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link
https://github.com/angular/angular-phonecat/commit/43ff5d76f1c0a464da67d691418e33e6c9d8dbc8 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_8 Next}</td>
</tr>
</table>
In this step we introduce angular's {@link angular.service.$route $route} service. This service
is usually used in conjunction with the {@link angular.widget.ng:view ng:view} directive. The
`$route` 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, and Back and Forward browser navigation.
We'll use {@link angular.service.$route $route} to implement two different views for our
application: one view presents the phone listing, and the other view presents the details for a
particular phone. We'll use {@link angular.widget.ng:view ng:view} to include one or the other of
those views in our main layout page (`index.html`). The view presented in the layout page is based
on which URL the user navigates to.
To manage our two different views, we'll move the existing phone list controller into a
sub-controller, add a second sub-controller to handle the phone details, and we'll create a new
root controller to implement the routing. (We'll save the implementation of the phone details
View for the next step.)
__`app/index.html`:__
<pre>
<body ng:controller="PhoneCatCtrl">
...
<ng:view></ng:view>
...
</pre>
__`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>
__`app/js/controller.js`:__
<pre>
/* App Controllers */
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'];
function PhoneListCtrl($xhr) {
var self = this;
$xhr('GET', 'phones/phones.json', function(code, response) {
self.phones = response;
});
self.orderProp = 'age';
}
//PhoneListCtrl.$inject = ['$xhr'];
function PhoneDetailCtrl() {}
</pre>
## Discussion:
We have many changes to discuss here in Step 7:
* __The View.__ Our View template in `index.html` has been reduced down to this:
`<ng:view></ng:view>`. It is now what we call a "layout template", because it contains
information common for all views, including the layout of our application. The {@link
angular.widget.ng:view ng:view} directive behaves like an "include" declaration (it's a
specialized sibling of the {@link angular.widget.ng:include ng:include} directive) that works
specifically with the {@link angular.service.$route $route} service. The View template associated
with the current route definition gets included "between those tags" (there's more to it than a
simple include, but that explanation will do for now).
* We added two new View templates:
* `app/partials/phone-list.html` for the phone list;
* `app/partials/phone-detail.html` for the phone details (just a stub for this step);
* __The Controller(s).__ We now have a new root controller (`PhoneCatCtrl`) and two
sub-controllers (`PhoneListCtrl` and `PhoneDetailCtrl`).
* __`$route.`__ The root controller's job now is to set up the `$route` configuration:
* When the fragment part of the URL in the browser ends in "/phones", `$route` grabs the
`phone-list.html` template, compiles it, and links it with a new scope that is controlled
by our `PhoneListCtrl` controller.
* When the URL ends in "/phones/:phoneId", `$route` compiles and links the
`phone-detail.html` template as it did with `phone-list.html`. But note the use of the
variable `:phoneId` in the `path` parameter of `$route.when()`: `$route` stores that
portion of the current URL fragment in its current parameters in a property called
`params.phoneId`. We made the `$route` parameters available to our sub-controllers in the
`$route.onChange()` function in our root controller. We will use the `phoneId` property
when we fetch the phone details in Step 8.
* Any other URL fragment gets redirected to `/phones`.
* __Deep Linking.__ In `$route`'s `onChange()` method, we copied {@link
http://en.wikipedia.org/wiki/Deep_linking deep linking} parameters to the `params` property in
the root scope, so we can use them in the child scopes managed by our sub-controllers.
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_6 Previous}</td>
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-7/app Example}</td>
<td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link
https://github.com/angular/angular-phonecat/commit/43ff5d76f1c0a464da67d691418e33e6c9d8dbc8 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_8 Next}</td>
</tr>
</table>
|