mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +00:00
134 lines
5.5 KiB
Text
134 lines
5.5 KiB
Text
|
|
@workInProgress
|
|||
|
|
@ngdoc overview
|
|||
|
|
@name Tutorial: Step 2
|
|||
|
|
@description
|
|||
|
|
<table id="tutorial_nav">
|
|||
|
|
<tr>
|
|||
|
|
<td id="previous_step">{@link tutorial.step_1 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/commit/02e30dd64e0e5554fbf4d442ade5b1a251f2bf56
|
|||
|
|
Code Diff}</td>
|
|||
|
|
<td id="next_step">{@link tutorial.step_3 Next}</td>
|
|||
|
|
</tr>
|
|||
|
|
</table>
|
|||
|
|
|
|||
|
|
An important feature of angular is the incorporation of the principles behind {@link
|
|||
|
|
http://en.wikipedia.org/wiki/Model–View–Controller 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.
|
|||
|
|
|
|||
|
|
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 small set 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 constructs two-way
|
|||
|
|
data-binding between the View and the Model. In angular, the View is a projection of the Model
|
|||
|
|
through the HTML template.
|
|||
|
|
|
|||
|
|
* __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 two-way 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.
|
|||
|
|
|
|||
|
|
So, our controller function becomes the {@link angular.scope scope} of our data model.
|
|||
|
|
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 some data, and that there are 3 records in the data set.
|
|||
|
|
|
|||
|
|
Angular's testing stack utilizes Jasmine's Behavior-driven Development (BDD) framework. You
|
|||
|
|
can learn about it 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_1 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/commit/02e30dd64e0e5554fbf4d442ade5b1a251f2bf56
|
|||
|
|
Code Diff}</td>
|
|||
|
|
<td id="next_step">{@link tutorial.step_3 Next}</td>
|
|||
|
|
</tr>
|
|||
|
|
</table>
|