We did a lot of basic training in the previous step, so now we can do some simple things. We're going to join the full-text search feature (yes, this is really very simple!) )。 At the same time, we will write an end-to-end test, because a good end-to-end test can be very helpful. It monitors your application and reports quickly in the event of a return.
Please reset your working directory:
git checkout -f step-3
Our app now has a search box. Notice that the list of phones on the page varies with the user's input in the search box.
The most important differences between steps 2 and 3 are listed below. You can see the whole difference on GitHub.
Controller
We do not make any changes to the controller.
Template
App/index.html
<div Class="Container-fluid"> <div Class="Row-fluid"> <div Class="Span2"> <!--Sidebar content-->Search:<input Ng-model="Query"> </div> <div Class="Span10"> <!--Body content--><ul class= "phones" > <li ng-repeat< Span class= "pun" >= "Phone in phones | Filter:query "> {{Phone.name}} <p> {{phone.snippet}}</p> </li> </ul> </div> </div></DIV>
We now add a <input>
label and use Angularjs's $filter function to handle the input of the ngrepeat instruction.
This allows the user to enter a search condition and immediately be able to see the search results for the phone list. Let's try to explain the new code:
Data binding: This is a core feature of Angularjs. When the page loads, Angularjs binds it to a variable of the same name in the data model, based on the name of the input box's property value, to ensure the synchronization of the two.
In this code, the name of the data entered by the user in the input box query
is immediately entered as the filter for the list iterator ( phone in phones | filter:
query '). When the data model causes iterator input to change, iterators can efficiently update the DOM to reflect the latest state of the data model.
Use filter
the filter: query
the value used by the filter function to create a query
new array that contains only matching records.
ngRepeat
filter
The view is automatically updated based on the array of cell phone record data generated by the filter. The whole process is transparent to the developer.
Test
In step 2, we learned how to write and run a test. Unit testing is very handy for testing the controllers and other components we write with JS, but it is not easy to test DOM operations and application integration. For these, end-to-end testing is a better choice.
The search feature is implemented entirely through templates and data binding, so our first end-to-end test verifies that these features are in line with our expectations.
Test/e2e/scenarios.js:
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 ' tobe (1 Input ' query ' Enter "Motorola" expect repeater ( phones Li ' count ()). tobe (2 }); });
Although the syntax of this test code looks very much like the unit tests we wrote earlier with Jasmine, the end-to-end test uses the interface provided by the Angularjs end-to-end tester.
Run an end-to-end test and open one of the following in the browser's new tab page:
- node. JS User: Http://localhost:8000/test/e2e/runner.html
- Users using a different HTTP server:
http://localhost:[port-number]/[context-path]/test/e2e/runner.html
- Visitors: http://angular.github.com/angular-phonecat/step-3/test/e2e/runner.html
This test verifies that the search box and the iterator are properly integrated. You can see how easy it is to write an end-to-end test in Angularjs. Although this example is just a simple test, it is easy to use it to build any of the complex, readable end-to-end tests.
Practice
index.html
Add a {{query}}
binding to the template to display query
the current values of the model in real time, and then see how they change depending on the value in the input box.
Now let's take a look at how we let the value of the query
model appear on the page header of the HTML.
You might think it's OK to title
add a binding on the label like this:
<title>Google Phone Gallery: {{query}}</title>
However, when you reload the page, you simply can't get the desired result. This is because the query
model is body
valid only within the scope of the element definition.
<body ng-controller="PhoneListCtrl">
If you want to <title>
bind an element to a query
model, you ngController
must move the declaration to the HTML
element, because it is title
body
the common ancestor of the element.
ng-app ng-controller="PhoneListCtrl">
Be careful to body
delete the declaration on the element ng-controller
.
When binding two curly braces on the title
element can achieve our goal, but you may find that the page is loading when they are displayed to the user to see. A better solution is to use ngbind or ngbindtemplate directives, which are not visible to the user when the page is loaded:
<title ng-bind-template="Google Phone Gallery: {{query}}">Google Phone Gallery</title>
test/e2e/scenarios.js
Add the describe
following end-to-end test code in the block:
It(' Should display the current filter value within a element with ID ' status ', function() {Expect(Element(' #status ').Text()).Tomatch(/current Filter: \s*$/);Input(' Query ').Enter(' Nexus '); Expect (element (text ()). tomatch (/current filter:nexus\s*$/ //alternative version of the last assertion that tests just the value of the Binding using ( ' #status ' expect (binding ( "query" Span class= "pun")). tobe (
Refresh the browser, and the end-to-end tester will report the test failure. In order for the test to pass, edit index.html
, add one id为“status”
div
or the p
element, the content is a query
binding, plus a Current filter:
prefix. For example:
<div id="status">Current filter: {{query}}</div>
Add a statement to the end-to-end test pause();
and run it again. You will find the tester paused! This gives you the opportunity to see the status of your app while the test is running. The test app is real-time! You can change the search content to prove it. With a little experience you will know how critical it is to quickly find problems in end-to-end testing.
Summarize
We have now added full-text search functionality and completed a test to prove that the search is right! Now let's move on to step 4来 to see how our mobile app adds sorting capabilities.