aboutsummaryrefslogtreecommitdiffstats
path: root/docs/tutorial.step_02.ngdoc
blob: 62becdba2d8584d6b83ad77a9777e063a284a159 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
@workInProgress
@ngdoc overview
@name Tutorial: Step 2
@description
<table id="tutorial_nav">
 <tr>
   <td id="previous_step">{@link tutorial.step_00 Previous}</td>
   <td id="step_result">{@link  http://angular.github.com/angular-phonecat/step-2/app Example}</td>
   <td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-1...step-2 Code
Diff}</td>
   <td id="next_step">{@link tutorial.step_00 Next}</td>
 </tr>
</table>

In the last step, we remembered what a basic, static web page looks like, and now we want to get
dynamic. There are many ways to do this, but an important feature of angular is the incorporation
of the principles behind {@link http://en.wikipedia.org/wiki/ModelViewController the MVC design
pattern} into client-side web apps. With that in mind, let's use a little angular and a little
JavaScript to add Model, View, and Controller components to our app, and change the static page
into one that is dynamically generated.

Our __View__ component is constructed by angular from this template:

__`app/index.html`:__
<pre>
...
<body ng:controller="PhoneListCtrl">

  <ul>
    <li ng:repeat="phone in phones">
      {{phone.name}}
      <p>{{phone.snippet}}</p>
    </li>
  </ul>

  <script src="lib/angular/angular.js" ng:autobind></script>
  <script src="js/controllers.js"></script>
</body>
...
</pre>

Our data __Model__ (a short list of phones in object literal notation) is instantiated within our
__Controller__ function (`PhoneListCtrl`): 

__`app/js/controllers.js`:__
<pre>
/* App Controllers */

function PhoneListCtrl() {
  this.phones = [{"name": "Nexus S",
                  "snippet": "Fast just got faster with Nexus S."},
                 {"name": "Motorola XOOM™ with Wi-Fi",
                  "snippet": "The Next, Next Generation tablet."},
                 {"name": "MOTOROLA XOOM™",
                  "snippet": "The Next, Next Generation tablet."}];
}
</pre>

The "Angular way" urges us to test as we develop:

__`test/unit/controllersSpec.js`:__
<pre>
/* jasmine specs for controllers go here */
describe('PhoneCat controllers', function() {

  describe('PhoneListCtrl', function(){

    it('should create "phones" model with 3 phones', function() {
      var ctrl = new PhoneListCtrl();
      expect(ctrl.phones.length).toBe(3);
    });
  });
});
</pre>

## Discussion:

So what were our changes from Step 1?

* __View template:__ We replaced the hard-coded phone list with the {@link
angular.widget.@ng:repeat ng:repeat widget} and two {@link guide.expression angular expressions}
enclosed in curly braces: `{{phone.name}}` and `{{phone.snippet}}`:

    * The `ng:repeat="phone in phones"` statement in the `<li>` tag is an angular repeater.  It
    tells angular to create a `<li>` element for each phone in the phones list, using the first
    `<li>` tag as the template. 

    * The curly braces around `phone.name` and `phone.snippet` are an example of {@link
    angular.markup angular markup}. The curly braces are shorthand for the angular directive
    {@link angular.directive.ng:bind ng:bind}.  They indicate to angular that these are template
    binding points. Binding points are locations in the template where angular creates
    data-binding between the View and the Model. In angular, the View is a projection of the Model
    through the HTML template. This means that whenever the model changes, angular refreshes the
    appropriate binding points, which updates the view.

* __Controller:__  At this point, it doesn't appear as if our controller is doing very much
controlling, but it is playing a crucial role: providing context for our data model so we can
establish data-binding between the model and the view.  Note in the following how we connected the
dots between our presentation, data, and logic components: 

    * The name of our controller function (in the JavaScript file `controllers.js`) matches the
    {@link angular.directive.ng:controller ng:controller} directive in the `<body>` tag
    (`PhoneListCtrl`). 
    * We instantiated our data within the scope of our controller function, and our template
    binding points are located within the block bounded by the `<body
    ng:controller="PhoneListCtrl>` tag.

    Angular uses scopes, along with the information contained in the template, data model, and
    controller to keep the Model and View separated but in sync: any changes to the model are
    reflected in the view; any changes that occur in the view are reflected in the model.

* __Model:__ For our data model, we created a simple array of phone records, specified in object
literal notation.

* __Testing:__ Ease of testing is another cornerstone of angular's design philosophy.  All we are
doing here is showing how easy it is to create a unit test using the technology baked into
angular.  The test verifies that we have 3 records in the phones array.

    To run this test, make sure you have a {@link tutorial test server running}, and type
    `./scripts/test.sh` from the command line.

    Angular developers prefer the syntax of Jasmine's Behavior-driven Development (BDD) framework
    when writing tests. So while Jasmine is not required by angular, we use it to write all tests
    in this tutorial. You can learn about Jasmine on the {@link http://pivotal.github.com/jasmine/
    Jasmine home page} and on the {@link https://github.com/pivotal/jasmine/wiki Jasmine wiki}.

<table id="tutorial_nav">
 <tr>
   <td id="previous_step">{@link tutorial.step_00 Previous}</td>
   <td id="step_result">{@link  http://angular.github.com/angular-phonecat/step-2/app Example}</td>
   <td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-1...step-2 Code
Diff}</td>
   <td id="next_step">{@link tutorial.step_00 Next}</td>
 </tr>
</table>