@ngdoc overview @name Cookbook: MVC @description MVC allows for a clean and 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 a set of objects and primitives that are referenced from the Scope ($scope) object. 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.

Tic-Tac-Toe

Next Player: {{nextMove}}
Player {{winner}} has won!
{{cell}}
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(); }
# 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 {@link api/ng.$rootScope.Scope#$watch $watch()} to set up a listener that invokes `readUrl()` when needed.