diff options
Diffstat (limited to 'docs/cookbook.mvc.ngdoc')
| -rw-r--r-- | docs/cookbook.mvc.ngdoc | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/docs/cookbook.mvc.ngdoc b/docs/cookbook.mvc.ngdoc index 2fa2c558..94688547 100644 --- a/docs/cookbook.mvc.ngdoc +++ b/docs/cookbook.mvc.ngdoc @@ -3,9 +3,13 @@ @name Cookbook: MVC @description -MVC allows for a clean an testable separation between the behavior (controller) and the view (HTML template). A Controller is just a JavaScript class which is grafted onto the scope of the view. This makes it very easy for the controller and the view to share the model. +MVC allows for a clean an testable separation between the behavior (controller) and the view +(HTML template). A Controller is just a JavaScript class which is grafted onto the scope of the +view. This makes it very easy for the controller and the view to share the model. -The model is simply the controller's this. This makes it very easy to test the controller in isolation since one can simply instantiate the controller and test without a view, because there is no connection between the controller and the view. +The model is simply the controller's this. This makes it very easy to test the controller in +isolation since one can simply instantiate the controller and test without a view, because there is +no connection between the controller and the view. <doc:example> @@ -21,7 +25,7 @@ The model is simply the controller's this. This makes it very easy to test the c 'cursor': 'pointer' }; this.reset(); - this.$watch('$location.hashPath', this.readUrl); + this.$watch('$location.hashSearch.board', this.readUrl); } TicTacToeCntl.prototype = { dropPiece: function(row, col) { @@ -54,16 +58,16 @@ The model is simply the controller's this. This makes it very easy to test the c }, setUrl: function(){ var rows = []; - angular.foreach(this.board, function(row){ + angular.forEach(this.board, function(row){ rows.push(row.join(',')); }); - this.$location.hashPath = rows.join(';') + '/' + this.nextMove; + this.$location.hashSearch.board = rows.join(';') + '/' + this.nextMove; }, readUrl: function(value) { if (value) { value = value.split('/'); this.nextMove = value[1]; - angular.foreach(value[0].split(';'), function(row, i){ + angular.forEach(value[0].split(';'), function(row, i){ this.board[i] = row.split(','); }, this); this.grade(); @@ -76,8 +80,8 @@ The model is simply the controller's this. This makes it very easy to test the c <h3>Tic-Tac-Toe</h3> <div ng:controller="TicTacToeCntl"> Next Player: {{nextMove}} - <div ng:show="winner">Player {{winner}} has won!</div> - <table> + <div class="winner" ng:show="winner">Player {{winner}} has won!</div> + <table class="board"> <tr ng:repeat="row in board" style="height:15px;"> <td ng:repeat="cell in row" ng:style="cellStyle" ng:click="dropPiece($parent.$index, $index)">{{cell}}</td> @@ -87,17 +91,35 @@ The model is simply the controller's this. This makes it very easy to test the c </div> </doc:source> <doc:scenario> + it('should play a game', function(){ + piece(1, 1); + expect(binding('nextMove')).toEqual('O'); + piece(3, 1); + expect(binding('nextMove')).toEqual('X'); + piece(1, 2); + piece(3, 2); + piece(1, 3); + expect(element('.winner').text()).toEqual('Player X has won!'); + }); + + function piece(row, col) { + element('.board tr:nth-child('+row+') td:nth-child('+col+')').click(); + } </doc:scenario> </doc:example> -Things to notice +# Things to notice -The controller is defined in JavaScript and has no reference to the rendering logic. -The controller is instantiated by <angular/> and injected into the view. -The controller can be instantiated in isolation (without a view) and the code will still execute. This makes it very testable. -The HTML view is a projection of the model. In the above example, the model is stored in the board variable. -All of the controller's properties (such as board and nextMove) are available to the view. -Changing the model changes the view. -The view can call any controller function. -In this example, the setUrl() and readUrl() functions copy the game state to/from the URL's hash so the browser's back button will undo game steps. See deep-linking. This example calls $watch() to set up a listener that invokes readUrl() when needed. +* The controller is defined in JavaScript and has no reference to the rendering logic. +* The controller is instantiated by <angular/> and injected into the view. +* The controller can be instantiated in isolation (without a view) and the code will still execute. + This makes it very testable. +* The HTML view is a projection of the model. In the above example, the model is stored in the + board variable. +* All of the controller's properties (such as board and nextMove) are available to the view. +* Changing the model changes the view. +* The view can call any controller function. +* In this example, the `setUrl()` and `readUrl()` functions copy the game state to/from the URL's + hash so the browser's back button will undo game steps. See deep-linking. This example calls + {@link angular.Scope.$watch $watch()} to set up a listener that invokes `readUrl()` when needed. |
