Improve this doc

In this step, you will implement the phone details view, which is displayed when a user clicks on a phone in the phone list.

Now when you click on a phone on the list, the phone details page with phone-specific information is displayed.

To implement the phone details view we will use $http to fetch our data, and we'll flesh out the phone-detail.html view template.

The most important changes are listed below. You can see the full diff on 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)

  1. {
  2. "additionalFeatures": "Contour Display, Near Field Communications (NFC),...",
  3. "android": {
  4. "os": "Android 2.3",
  5. "ui": "Android"
  6. },
  7. ...
  8. "images": [
  9. "img/phones/nexus-s.0.jpg",
  10. "img/phones/nexus-s.1.jpg",
  11. "img/phones/nexus-s.2.jpg",
  12. "img/phones/nexus-s.3.jpg"
  13. ],
  14. "storage": {
  15. "flash": "16384MB",
  16. "ram": "512MB"
  17. }
  18. }

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

We'll expand the PhoneDetailCtrl by using the $http service to fetch the json files. This works the same way as the phone list controller.

app/js/controllers.js:

  1. var phonecatControllers = angular.module('phonecatControllers',[]);
  2.  
  3. phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
  4. function($scope, $routeParams, $http) {
  5. $http.get('phones/' + $routeParams.phoneId + '.json').success(function(data) {
  6. $scope.phone = data;
  7. });
  8. }]);

To construct the URL for the HTTP request, we use $routeParams.phoneId extracted from the current route by the $route service.

Template

The TBD placeholder line has been replaced with lists and bindings that comprise the phone details. Note where we use the angular {{expression}} markup and ngRepeat to project phone data from our model into the view.

app/partials/phone-detail.html:

  1. <img ng-src="{{phone.images[0]}}" class="phone">
  2.  
  3. <h1>{{phone.name}}</h1>
  4.  
  5. <p>{{phone.description}}</p>
  6.  
  7. <ul class="phone-thumbs">
  8. <li ng-repeat="img in phone.images">
  9. <img ng-src="{{img}}">
  10. </li>
  11. </ul>
  12.  
  13. <ul class="specs">
  14. <li>
  15. <span>Availability and Networks</span>
  16. <dl>
  17. <dt>Availability</dt>
  18. <dd ng-repeat="availability in phone.availability">{{availability}}</dd>
  19. </dl>
  20. </li>
  21. ...
  22. </li>
  23. <span>Additional Features</span>
  24. <dd>{{phone.additionalFeatures}}</dd>
  25. </li>
  26. </ul>

TODO! Experiments - 图1

Test

We wrote a new unit test that is similar to the one we wrote for the PhoneListCtrl controller in step 5.

test/unit/controllersSpec.js:

  1. ...
  2. describe('PhoneDetailCtrl', function(){
  3. var scope, $httpBackend, ctrl;
  4.  
  5. beforeEach(inject(function(_$httpBackend_, $rootScope, $routeParams, $controller) {
  6. $httpBackend = _$httpBackend_;
  7. $httpBackend.expectGET('phones/xyz.json').respond({name:'phone xyz'});
  8.  
  9. $routeParams.phoneId = 'xyz';
  10. scope = $rootScope.$new();
  11. ctrl = $controller('PhoneDetailCtrl', {$scope: scope});
  12. }));
  13.  
  14.  
  15. it('should fetch phone detail', function() {
  16. expect(scope.phone).toBeUndefined();
  17. $httpBackend.flush();
  18.  
  19. expect(scope.phone).toEqual({name:'phone xyz'});
  20. });
  21. });
  22. ...

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

  1. Chrome 22.0: Executed 3 of 3 SUCCESS (0.039 secs / 0.012 secs)

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:

  1. ...
  2. describe('Phone detail view', function() {
  3.  
  4. beforeEach(function() {
  5. browser().navigateTo('../../app/index.html#/phones/nexus-s');
  6. });
  7.  
  8.  
  9. it('should display nexus-s page', function() {
  10. expect(binding('phone.name')).toBe('Nexus S');
  11. });
  12. });
  13. ...

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 Angular's server.

Experiments

Summary

Now that the phone details view is in place, proceed to step 9 to learn how to write your own custom display filter.