2012-03-30 21:02:26 +00:00
|
|
|
@ngdoc overview
|
|
|
|
|
@name Tutorial: 8 - More Templating
|
|
|
|
|
@description
|
|
|
|
|
|
2012-04-29 05:45:28 +00:00
|
|
|
<ul doc-tutorial-nav="8"></ul>
|
2012-03-30 21:02:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
In this step, you will implement the phone details view, which is displayed when a user clicks on a
|
|
|
|
|
phone in the phone list.
|
|
|
|
|
|
|
|
|
|
|
2012-04-29 05:45:28 +00:00
|
|
|
<div doc-tutorial-reset="8"></div>
|
2012-03-30 21:02:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Now when you click on a phone on the list, the phone details page with phone-specific information
|
|
|
|
|
is displayed.
|
|
|
|
|
|
2012-06-12 06:49:24 +00:00
|
|
|
To implement the phone details view we will use {@link api/ng.$http $http} to fetch
|
2012-07-15 16:18:42 +00:00
|
|
|
our data, and we'll flesh out the `phone-detail.html` view template.
|
2012-03-30 21:02:26 +00:00
|
|
|
|
|
|
|
|
The most important changes are listed below. You can see the full diff on {@link
|
|
|
|
|
https://github.com/angular/angular-phonecat/compare/step-7...step-8
|
|
|
|
|
GitHub}:
|
|
|
|
|
|
|
|
|
|
## Data
|
|
|
|
|
|
|
|
|
|
In addition to `phones.json`, the `app/phones/` directory also contains one json file for each
|
|
|
|
|
phone:
|
|
|
|
|
|
|
|
|
|
__`app/phones/nexus-s.json`:__ (sample snippet)
|
|
|
|
|
<pre>
|
|
|
|
|
{
|
|
|
|
|
"additionalFeatures": "Contour Display, Near Field Communications (NFC),...",
|
|
|
|
|
"android": {
|
|
|
|
|
"os": "Android 2.3",
|
|
|
|
|
"ui": "Android"
|
|
|
|
|
},
|
|
|
|
|
...
|
|
|
|
|
"images": [
|
|
|
|
|
"img/phones/nexus-s.0.jpg",
|
|
|
|
|
"img/phones/nexus-s.1.jpg",
|
|
|
|
|
"img/phones/nexus-s.2.jpg",
|
|
|
|
|
"img/phones/nexus-s.3.jpg"
|
|
|
|
|
],
|
|
|
|
|
"storage": {
|
|
|
|
|
"flash": "16384MB",
|
|
|
|
|
"ram": "512MB"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Each of these files describes various properties of the phone using the same data structure. We'll
|
|
|
|
|
show this data in the phone detail view.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Controller
|
|
|
|
|
|
2012-04-27 22:18:54 +00:00
|
|
|
We'll expand the `PhoneDetailCtrl` by using the `$http` service to fetch the json files. This works
|
2012-03-30 21:02:26 +00:00
|
|
|
the same way as the phone list controller.
|
|
|
|
|
|
2012-07-15 16:18:42 +00:00
|
|
|
__`app/js/controllers.js`:__
|
2012-03-30 21:02:26 +00:00
|
|
|
<pre>
|
2013-10-03 10:58:47 +00:00
|
|
|
var phonecatApp = angular.module('phonecatApp',[]);
|
|
|
|
|
phonecatApp.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http', function($scope, $routeParams, $http) {
|
2012-04-27 22:18:54 +00:00
|
|
|
$http.get('phones/' + $routeParams.phoneId + '.json').success(function(data) {
|
|
|
|
|
$scope.phone = data;
|
2012-03-30 21:02:26 +00:00
|
|
|
});
|
2013-10-03 09:16:44 +00:00
|
|
|
}]);
|
2012-03-30 21:02:26 +00:00
|
|
|
</pre>
|
|
|
|
|
|
2012-04-27 22:18:54 +00:00
|
|
|
To construct the URL for the HTTP request, we use `$routeParams.phoneId` extracted from the current
|
|
|
|
|
route by the `$route` service.
|
2012-03-30 21:02:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
## Template
|
|
|
|
|
|
|
|
|
|
The TBD placeholder line has been replaced with lists and bindings that comprise the phone details.
|
2012-07-19 15:44:06 +00:00
|
|
|
Note where we use the angular `{{expression}}` markup and `ngRepeat` to project phone data from
|
2012-03-30 21:02:26 +00:00
|
|
|
our model into the view.
|
|
|
|
|
|
|
|
|
|
|
2012-07-15 16:18:42 +00:00
|
|
|
__`app/partials/phone-detail.html`:__
|
2012-03-30 21:02:26 +00:00
|
|
|
<pre>
|
2012-04-27 22:18:54 +00:00
|
|
|
<img ng-src="{{phone.images[0]}}" class="phone">
|
2012-03-30 21:02:26 +00:00
|
|
|
|
|
|
|
|
<h1>{{phone.name}}</h1>
|
|
|
|
|
|
|
|
|
|
<p>{{phone.description}}</p>
|
|
|
|
|
|
|
|
|
|
<ul class="phone-thumbs">
|
2012-04-27 22:18:54 +00:00
|
|
|
<li ng-repeat="img in phone.images">
|
|
|
|
|
<img ng-src="{{img}}">
|
2012-03-30 21:02:26 +00:00
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
<ul class="specs">
|
|
|
|
|
<li>
|
|
|
|
|
<span>Availability and Networks</span>
|
|
|
|
|
<dl>
|
|
|
|
|
<dt>Availability</dt>
|
2012-04-27 22:18:54 +00:00
|
|
|
<dd ng-repeat="availability in phone.availability">{{availability}}</dd>
|
2012-03-30 21:02:26 +00:00
|
|
|
</dl>
|
|
|
|
|
</li>
|
|
|
|
|
...
|
|
|
|
|
</li>
|
|
|
|
|
<span>Additional Features</span>
|
|
|
|
|
<dd>{{phone.additionalFeatures}}</dd>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</pre>
|
|
|
|
|
|
2012-04-27 22:18:54 +00:00
|
|
|
<div style="display: none">
|
|
|
|
|
TODO!
|
2012-04-29 05:45:28 +00:00
|
|
|
<img class="diagram" src="img/tutorial/tutorial_08-09_final.png">
|
2012-04-27 22:18:54 +00:00
|
|
|
</div>
|
2012-03-30 21:02:26 +00:00
|
|
|
|
|
|
|
|
## Test
|
|
|
|
|
|
|
|
|
|
We wrote a new unit test that is similar to the one we wrote for the `PhoneListCtrl` controller in
|
|
|
|
|
step 5.
|
|
|
|
|
|
2012-07-15 16:18:42 +00:00
|
|
|
__`test/unit/controllersSpec.js`:__
|
2012-03-30 21:02:26 +00:00
|
|
|
<pre>
|
|
|
|
|
...
|
2012-04-27 22:18:54 +00:00
|
|
|
describe('PhoneDetailCtrl', function(){
|
|
|
|
|
var scope, $httpBackend, ctrl;
|
|
|
|
|
|
|
|
|
|
beforeEach(inject(function(_$httpBackend_, $rootScope, $routeParams, $controller) {
|
|
|
|
|
$httpBackend = _$httpBackend_;
|
|
|
|
|
$httpBackend.expectGET('phones/xyz.json').respond({name:'phone xyz'});
|
2012-03-30 21:02:26 +00:00
|
|
|
|
2012-04-27 22:18:54 +00:00
|
|
|
$routeParams.phoneId = 'xyz';
|
|
|
|
|
scope = $rootScope.$new();
|
2013-10-03 10:58:47 +00:00
|
|
|
ctrl = $controller('PhoneDetailCtrl', {$scope: scope});
|
2012-04-27 22:18:54 +00:00
|
|
|
}));
|
2012-03-30 21:02:26 +00:00
|
|
|
|
2012-04-27 22:18:54 +00:00
|
|
|
|
|
|
|
|
it('should fetch phone detail', function() {
|
|
|
|
|
expect(scope.phone).toBeUndefined();
|
|
|
|
|
$httpBackend.flush();
|
|
|
|
|
|
|
|
|
|
expect(scope.phone).toEqual({name:'phone xyz'});
|
2012-03-30 21:02:26 +00:00
|
|
|
});
|
2012-04-27 22:18:54 +00:00
|
|
|
});
|
2012-03-30 21:02:26 +00:00
|
|
|
...
|
|
|
|
|
</pre>
|
|
|
|
|
|
2013-04-15 11:28:31 +00:00
|
|
|
You should now see the following output in the Karma tab:
|
2012-03-30 21:02:26 +00:00
|
|
|
|
2012-10-18 09:33:45 +00:00
|
|
|
Chrome 22.0: Executed 3 of 3 SUCCESS (0.039 secs / 0.012 secs)
|
2012-03-30 21:02:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
We also added a new end-to-end test that navigates to the Nexus S detail page and verifies that the
|
|
|
|
|
heading on the page is "Nexus S".
|
|
|
|
|
|
|
|
|
|
__`test/e2e/scenarios.js`:__
|
|
|
|
|
<pre>
|
|
|
|
|
...
|
|
|
|
|
describe('Phone detail view', function() {
|
|
|
|
|
|
|
|
|
|
beforeEach(function() {
|
|
|
|
|
browser().navigateTo('../../app/index.html#/phones/nexus-s');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('should display nexus-s page', function() {
|
|
|
|
|
expect(binding('phone.name')).toBe('Nexus S');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
...
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
|
2012-10-18 09:33:45 +00:00
|
|
|
You can now rerun `./scripts/e2e-test.sh` or refresh the browser tab with the end-to-end test
|
|
|
|
|
runner to see the tests run, or you can see them running on {@link
|
2012-03-30 21:02:26 +00:00
|
|
|
http://angular.github.com/angular-phonecat/step-8/test/e2e/runner.html
|
2012-07-15 16:18:42 +00:00
|
|
|
Angular's server}.
|
2012-03-30 21:02:26 +00:00
|
|
|
|
2012-10-18 09:33:45 +00:00
|
|
|
|
2012-03-30 21:02:26 +00:00
|
|
|
# Experiments
|
|
|
|
|
|
|
|
|
|
* Using the {@link guide/dev_guide.e2e-testing Angular's end-to-end test runner API}, write a test
|
|
|
|
|
that verifies that we display 4 thumbnail images on the Nexus S details page.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Summary
|
|
|
|
|
|
|
|
|
|
Now that the phone details view is in place, proceed to {@link step_09 step 9} to learn how to
|
|
|
|
|
write your own custom display filter.
|
|
|
|
|
|
|
|
|
|
|
2012-04-29 05:45:28 +00:00
|
|
|
<ul doc-tutorial-nav="8"></ul>
|