aboutsummaryrefslogtreecommitdiffstats
path: root/docs/cookbook.mvc.ngdoc
diff options
context:
space:
mode:
Diffstat (limited to 'docs/cookbook.mvc.ngdoc')
-rw-r--r--docs/cookbook.mvc.ngdoc56
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.