diff options
| author | Igor Minar | 2012-01-15 23:28:10 -0800 | 
|---|---|---|
| committer | Igor Minar | 2012-01-17 09:49:37 -0800 | 
| commit | 92af30ce6e99676c71c85bd08962b68629564908 (patch) | |
| tree | 4adf4b56cbf7c9fb6ee9dee8f40dd16fb2199842 /docs/content/tutorial/step_11.ngdoc | |
| parent | 54581d36df74ac128a078aafb3e4b66e0b1599f3 (diff) | |
| download | angular.js-92af30ce6e99676c71c85bd08962b68629564908.tar.bz2 | |
docs(*): various doc fixes
Diffstat (limited to 'docs/content/tutorial/step_11.ngdoc')
| -rw-r--r-- | docs/content/tutorial/step_11.ngdoc | 208 | 
1 files changed, 0 insertions, 208 deletions
| diff --git a/docs/content/tutorial/step_11.ngdoc b/docs/content/tutorial/step_11.ngdoc deleted file mode 100644 index c6b70065..00000000 --- a/docs/content/tutorial/step_11.ngdoc +++ /dev/null @@ -1,208 +0,0 @@ -@ngdoc overview -@name Tutorial: 11 - REST and Custom Services -@description - -<ul doc:tutorial-nav="11"></ul> - - -In this step, you will improve the way our app fetches data. - - -<doc:tutorial-instructions step="11"></doc:tutorial-instructions> - - -The last improvement we will make to our app is to define a custom service that represents a {@link -http://en.wikipedia.org/wiki/Representational_State_Transfer RESTful} client. Using this client we -can make xhr requests for data in an easier way, without having to deal with the lower-level {@link -api/angular.module.ng.$xhr $xhr} API, HTTP methods and URLs. - -The most important changes are listed below. You can see the full diff on {@link -https://github.com/angular/angular-phonecat/compare/step-10...step-11 -GitHub}: - - -## Template - -The custom service is defined in `app/js/services.js` so we need to include this file in our layout -template: - -__`app/index.html`.__ -<pre> -... -  <script src="js/services.js"></script> -... -</pre> - -## Service - -__`app/js/services.js`.__ -<pre> - angular.module.ng('Phone', function($resource) { -  return $resource('phones/:phoneId.json', {}, { -    query: {method: 'GET', params: {phoneId: 'phones'}, isArray: true} -  }); - }); -</pre> - -We used the {@link api/angular.module.ng} API to register a custom service. We passed in the name of -the service - 'Phone' - and a factory function. The factory function is similar to a controller's -constructor in that both can declare dependencies via function arguments. The Phone service -declared a dependency on the `$resource` service. - -The {@link api/angular.module.ng.$resource `$resource`} service makes it easy to create a {@link -http://en.wikipedia.org/wiki/Representational_State_Transfer RESTful} client with just a few lines -of code. This client can then be used in our application, instead of the lower-level {@link -api/angular.module.ng.$xhr $xhr} service. - - -## Controller - -We simplified our sub-controllers (`PhoneListCtrl` and `PhoneDetailCtrl`) by factoring out the -lower-level {@link api/angular.module.ng.$xhr $xhr} service, replacing it with a new service called -`Phone`. Angular's {@link api/angular.module.ng.$resource `$resource`} service is easier to use than -{@link api/angular.module.ng.$xhr $xhr} for interacting with data sources exposed as RESTful -resources. It is also easier now to understand what the code in our controllers is doing. - -__`app/js/controllers.js`.__ -<pre> -... - -function PhoneListCtrl(Phone) { -  this.orderProp = 'age'; -  this.phones = Phone.query(); -} -//PhoneListCtrl.$inject = ['Phone']; - - -function PhoneDetailCtrl(Phone) { -  var self = this; - -  self.phone = Phone.get({phoneId: self.params.phoneId}, function(phone) { -    self.mainImageUrl = phone.images[0]; -  }); - -  ... -} -//PhoneDetailCtrl.$inject = ['Phone']; -</pre> - -Notice how in `PhoneListCtrl` we replaced: - -    $xhr('GET', 'phones/phones.json', function(code, response) { -      self.phones = response; -    }); - -with: - -    this.phones = Phone.query(); - -This is a simple statement that we want to query for all phones. - -An important thing to notice in the code above is that we don't pass any callback functions when -invoking methods of our Phone service. Although it looks as if the result were returned -synchronously, that is not the case at all. What is returned synchronously is a "future" — an -object, which will be filled with data when the xhr response returns. Because of the data-binding -in angular, we can use this future and bind it to our template. Then, when the data arrives, the -view will automatically update. - -Sometimes, relying on the future object and data-binding alone is not sufficient to do everything -we require, so in these cases, we can add a callback to process the server response. The -`PhoneDetailCtrl` controller illustrates this by setting the `mainImageUrl` in a callback. - - -## Test - -We have modified our unit tests to verify that our new service is issuing HTTP requests and -processing them as expected. The tests also check that our controllers are interacting with the -service correctly. - -The {@link api/angular.module.ng.$resource $resource} service augments the response object with -methods for updating and deleting the resource. If we were to use the standard `toEqual` matcher, -our tests would fail because the test values would not match the responses exactly. To solve the -problem, we use a newly-defined `toEqualData` {@link -http://pivotal.github.com/jasmine/jsdoc/symbols/jasmine.Matchers.html Jasmine matcher}. When the -`toEqualData` matcher compares two objects, it takes only object properties into account and -ignores methods. - - -__`test/unit/controllersSpec.js`:__ -<pre> -describe('PhoneCat controllers', function() { - -  beforeEach(function() { -    this.addMatchers({ -      toEqualData: function(expected) { -        return angular.equals(this.actual, expected); -      } -    }); -  }); - -  describe('PhoneListCtrl', function() { -    var scope, $browser, ctrl; - -    beforeEach(function() { -      scope = angular.module.ng.$rootScope.Scope(); -      $browser = scope.$service('$browser'); - -      $browser.xhr.expectGET('phones/phones.json') -          .respond([{name: 'Nexus S'}, {name: 'Motorola DROID'}]); -      ctrl = scope.$new(PhoneListCtrl); -    }); - -    it('should create "phones" model with 2 phones fetched from xhr', function() { -      expect(ctrl.phones).toEqual([]); -      $browser.xhr.flush(); - -      expect(ctrl.phones).toEqualData([{name: 'Nexus S'}, -                                       {name: 'Motorola DROID'}]); -    }); - -    it('should set the default value of orderProp model', function() { -      expect(ctrl.orderProp).toBe('age'); -    }); -  }); - - -  describe('PhoneDetailCtrl', function() { -    var scope, $browser, ctrl; - -    beforeEach(function() { -      scope = angular.module.ng.$rootScope.Scope(); -      $browser = scope.$service('$browser'); -    }); - -    beforeEach(function() { -      scope = angular.module.ng.$rootScope.Scope(); -      $browser = scope.$service('$browser'); -    }); - -    it('should fetch phone detail', function() { -      scope.params = {phoneId:'xyz'}; -      $browser.xhr.expectGET('phones/xyz.json').respond({name:'phone xyz'}); -      ctrl = scope.$new(PhoneDetailCtrl); - -      expect(ctrl.phone).toEqualData({}); -      $browser.xhr.flush(); - -      expect(ctrl.phone).toEqualData({name:'phone xyz'}); -    }); -  }); -}); -</pre> - -To run the unit tests, execute the `./scripts/test.sh` script and you should see the following -output. - -    Chrome: Runner reset. -    .... -    Total 4 tests (Passed: 4; Fails: 0; Errors: 0) (3.00 ms) -      Chrome 11.0.696.57 Mac OS: Run 4 tests (Passed: 4; Fails: 0; Errors 0) (3.00 ms) - - -# Summary - -There you have it!  We have created a web app in a relatively short amount of time. In the {@link -the_end closing notes} we'll cover were to go from here. - - -<ul doc:tutorial-nav="11"></ul> | 
