We have done a lot of basic training in the previous step, so now we can do some simple things. We want to add the full text search function (yes, this is really very simple!). At the same time, we will also write an end-to-end test, because a good end-to-end test can help a lot. It monitors your app and reports quickly when regression occurs.
Please reset the working directory:
git checkout -f step-3
Our app now has a search box. Notice that the phone list on the page changes as the user enters in the search box.
The most important differences between Step 2 and Step 3 are listed below. You can see the complete difference in GitHub.
Controller
We do not make any changes to the controller.
template
app/index.html
<div> <div> <div> <!--Sidebar content--> Search: <input ng-model="query"> </div> <div> <!--Body content--> <ul> <li ng-repeat="phone in phones | filter:query"> {{phone.name}} <p>{{phone.snippet}}</p> </li> </ul> </div> </div></div>We now add a <input> tag and use AngularJS's $filter function to handle the input of the ngRepeat directive.
This allows users to enter a search criteria and immediately see the search results for the phone list. Let's explain the new code:
Data binding: This is a core feature of AngularJS. When the page is loaded, AngularJS will bind it with variables with the same name in the data model based on the property value name of the input box to ensure synchronization between the two.
In this code, the data name entered by the user in the input box is called query, which will be immediately used as input to its filter by the list iterator (phone in phones | filter:query`). When the data model causes changes in the iterator input, the iterator can efficiently update the DOM to reflect the latest state of the data model.
Use filter filter: The filter function uses the value of the query to create a new array that only matches the query records.
ngRepeat will automatically update the view based on the mobile record data array generated by the filter 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 convenient to test the controllers and other components we write in js, but it cannot easily test DOM operations and application integration. For these, end-to-end testing is a better choice.
Search features are implemented entirely through template and data binding, so our first end-to-end tests verify that these features meet 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').count()).toBe(1); input('query').enter('motorola'); expect(repeater('.phones li').count()).toBe(2); }); }); });Although the syntax of this test code looks very similar to the unit test we wrote in Jasmine before, the end-to-end test uses the interface provided by the AngularJS end-to-end tester.
Run an end-to-end test and open any of the following in the new browser tab:
node.js user: http://localhost:8000/test/e2e/runner.html
Users using other http servers: http://localhost:[port-number]/[context-path]/test/e2e/runner.html
Visitor: http://angular.github.com/angular-phonecat/step-3/test/e2e/runner.html
This test verifies that the search box and iterator are correctly integrated. You can find 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 build any complex, readable end-to-end test.
practise
Add a {{query}} binding to the index.html template to display the current value of the query model in real time, and then observe how they change according to the value in the input box.
Now let's take a look at how we can make the query model's value appear on the HTML page title.
You might think that adding a binding to the title tag like this:
<title>Google Phone Gallery: {{query}}</title>
However, when you reload the page, you simply cannot get the desired result. This is because the query model is only valid within the scope defined by the body element.
<body ng-controller="PhoneListCtrl">
If you want the <title> element to bind to the query model, you must move the ngController declaration to the HTML element, because it is the common ancestor of the title and body element.
<html ng-app ng-controller="PhoneListCtrl">
Be sure to delete the ng-controller declaration on the body element.
We can achieve our goal when binding two curly braces on the title element, but you may find that they are already displayed to the user when the page is loading. A better solution is to use ngBind or ngBindTemplate directives, which are invisible to the user when the page is loaded:
<title ng-bind-template="Google Phone Gallery: {{query}}">Google Phone Gallery</title>
Add the following end-to-end test codes to the describe block of test/e2e/scenarios.js:
it('should display the current filter value within an element with id "status"', function() { expect(element('#status').text()).toMatch(/Current filter: /s*$/); input('query').enter('nexus'); expect(element('#status').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')).toBe('nexus');});Refresh the browser and the end-to-end tester will report the test failure. To get the test passed, edit index.html and add a div or p element with id "status", which is a query binding, and the current filter: prefix. For example:
<div id="status">Current filter: {{query}}</div>
Add a pause(); statement to the end-to-end test and run it again. You will find that the tester is paused! This allows you to have the opportunity to view the status of your application during the test run. Testing applications are real-time! You can change the search content to prove it. With a little experience you will know how critical this is to quickly find problems in end-to-end testing.
Summarize
We have now added a full-text search feature and completed a test to prove that the search is right! Now let's move on to step 4 to see the addition of sorting function to our mobile app.
The above is a compilation of the AngularJS iterator filtering data, and we will continue to add relevant information in the future. Thank you for your support for this site!