new batch of tutorial docs

This commit is contained in:
Igor Minar
2011-05-02 10:16:50 -07:00
parent 11e9572b95
commit 6181ca600d
13 changed files with 1900 additions and 1588 deletions

View File

@@ -1,108 +1,142 @@
@workInProgress
@ngdoc overview
@name Tutorial: Step 3
@description
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_02 Previous}</td>
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Example}</td>
<td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link
https://github.com/angular/angular-phonecat/commit/a03815f8fb00217f5f9c1d3ef83282f79818e706 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_04 Next}</td>
</tr>
</table>
We did a lot of work in laying the foundation of our app in the last step, so now we'll do
something simple, and add full text search. We will also write an end-to-end test, because a good
end-to-end test is a good friend. It stays with your app, keeps an eye on it, and quickly detects
regressions.
__`app/index.html`:__
<pre>
...
Fulltext Search: <input name="query"/>
<ul class="phones">
<li ng:repeat="phone in phones.$filter(query)">
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
...
</pre>
__`test/e2e/scenarios.js`:__
<pre>
/* jasmine-like end2end tests go here */
describe('PhoneCat App', function() {
describe('Phone list view', function() {
beforeEach(function() {
browser().navigateTo('../../app/index.html');
});
it('should filter the phone list as user types into the search box', function() {
expect(repeater('.phones li').count()).toBe(3);
input('query').enter('nexus');
expect(repeater('.phones li').count()).toBe(1);
input('query').enter('motorola');
expect(repeater('.phones li').count()).toBe(2);
});
});
});
</pre>
## Discussion:
We continued using the same controller that we set up in Step 2, but we added the following
features to our app:
* __Search Box:__ A standard HTML `<input>` tag combined with angular's {@link
angular.Array.filter $filter} utility (added to the repeater) lets a user type in search criteria
and immediately see the effects of their search on the phone list. This new code demonstrates the
following:
* Two way Data-binding. This is one of the core features in angular. When the page loads,
angular binds the name of the input box to a variable of the same name in the data model and
keeps the two in sync.
In this example, the data that you type into the input box (named __`query`__) is immediately
available as a filter input in the list repeater (`phone in phones.$filter(`__`query`__`)`).
Whenever the data model changes and this change causes the input to the repeater to change, the
repeater will efficiently update the DOM to reflect the current state of the model.
* Use of `$filter` in a template. The `$filter` function is one of several built-in {@link
angular.Array angular functions} that augment JavaScript arrays during their evaluation as
angular expressions. In {@link guide.expression angular expressions}, these array utilities are
available as array methods. (They are prefixed with a $ to avoid naming collisions.)
* `ng:repeat` automatically shrinks and grows the number of phones in the View, via DOM
manipulation that is completely transparent to the developer. If you've written any DOM
manipulation code, this should make you happy.
* __CSS:__ We added in some minimal CSS to the file we set up in Step 0: `./css/app.css`.
* __Testing:__ To run the end to end test, open http://localhost:8000/test/e2e/runner.html in
your browser. This end-to-end test shows the following:
* Proof that the search box and the repeater are correctly wired together.
* How easy it is to write end-to-end tests. This is just a simple test, but the point here is
to show how easy it is to set up a functional, readable, end-to-end test.
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_02 Previous}</td>
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Example}</td>
<td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link
https://github.com/angular/angular-phonecat/commit/a03815f8fb00217f5f9c1d3ef83282f79818e706 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_04 Next}</td>
</tr>
</table>
@ngdoc overview
@name Tutorial: Step 3
@description
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_02 Previous}</td>
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Live
Demo}</td>
<td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-2...step-3 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_04 Next}</td>
</tr>
</table>
We did a lot of work in laying a foundation for the app in the last step, so now we'll do
something simple, and add full text search (yes, it will be simple!). We will also write an
end-to-end test, because a good end-to-end test is a good friend. It stays with your app, keeps an
eye on it, and quickly detects regressions.
1. Reset your workspace to Step 3 using:
git checkout --force step-3
or
./goto_step.sh 3
2. Refresh your browser or check the app out on {@link
http://angular.github.com/angular-phonecat/step-3/app our server}. The app now has a search box.
The phone list on the page changes depending on what a user types into the search box.
The most important changes are listed below. You can see the full diff on {@link
https://github.com/angular/angular-phonecat/compare/step-2...step-3
GitHub}:
## Controller
We made no changes to the controller.
## Template
__`app/index.html`:__
<pre>
...
Fulltext Search: <input name="query"/>
<ul class="phones">
<li ng:repeat="phone in phones.$filter(query)">
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
...
</pre>
We added a standard HTML `<input>` tag and use angular's {@link angular.Array.filter $filter}
function to process the input for the `ng:repeater`.
This lets a user enter search criteria and immediately see the effects of their search on the
phone list. This new code demonstrates the following:
* Data-binding. This is one of the core features in angular. When the page loads, angular binds
the name of the input box to a variable of the same name in the data model and keeps the two in
sync.
In this code, the data that a user types into the input box (named __`query`__) is immediately
available as a filter input in the list repeater (`phone in phones.$filter(`__`query`__`)`).
When changes to the data model cause the repeater's input to change, the repeater efficiently
updates the DOM to reflect the current state of the model.
* Use of `$filter`. The `{@link angular.Array.filter $filter}` method, uses the `query` value, to
create a new array that contains only those records that match the `query`.
* `ng:repeat` automatically updates the view in response to the changing number of phones returned
by the `$filter`. The process is completely transparent to the developer.
## Test
In Step 2, we learned how to write and run unit tests. Unit tests are perfect for testing
controllers and other components of our application written in JavaScript, but they can't easily
test DOM manipulation or the wiring of our application. For these, an end-to-end test is a much
better choice.
The search feature was fully implemented via templates and data-binding, so we'll write our first
end-to-end test, to verify that the feature works.
__`test/e2e/scenarios.js`:__
<pre>
describe('PhoneCat App', function() {
describe('Phone list view', function() {
beforeEach(function() {
browser().navigateTo('../../app/index.html');
});
it('should filter the phone list as user types into the search box', function() {
expect(repeater('.phones li').count()).toBe(3);
input('query').enter('nexus');
expect(repeater('.phones li').count()).toBe(1);
input('query').enter('motorola');
expect(repeater('.phones li').count()).toBe(2);
});
});
});
</pre>
Even though the syntax of this test looks very much like our controller unit test written with
Jasmine, the end-to-end test uses APIs of {@link
https://docs.google.com/document/d/11L8htLKrh6c92foV71ytYpiKkeKpM4_a5-9c3HywfIc/edit?hl=en&pli=1#
angular's end-to-end test runner}.
To run the end-to-end test, open the following in a new browser tab:
* node.js users: http://localhost:8000/test/e2e/runner.html
* users with other http servers:
http://localhost:[*port-number*]/[*context-path*]/test/e2e/runner.html
* casual reader: http://angular.github.com/angular-phonecat/step-3/test/e2e/runner.html
This test verifies that the search box and the repeater are correctly wired together. Notice how
easy it is to write end-to-end tests in angular. Although this example is for a simple test, it
really is that easy to set up any functional, readable, end-to-end test.
Now that you've verified everything, go to Step 4 to learn how to add sorting capability to the
phone list app.
<table id="tutorial_nav">
<tr>
<td id="previous_step">{@link tutorial.step_02 Previous}</td>
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Live
Demo}</td>
<td id="tut_home">{@link tutorial Tutorial Home}</td>
<td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-2...step-3 Code
Diff}</td>
<td id="next_step">{@link tutorial.step_04 Next}</td>
</tr>
</table>