Your First AngularJS App: Filtering and Ordering Model Data

In Chapter 14, I describe the AngularJS filter feature, which provides a nice way of preparing data in the model for display in views without having to create behaviors. There is nothing wrong with using behaviors, but filters tend to be more general-purpose and lend themselves to reuse across an application. Listing 2-10 shows the changes I made to the todo.html file to demonstrate filtering.

Listing2-10. Adding Filtering to the todo.html File

<tbody>

<tr ng-repeat=”item in todo.items | filter:{done: false} | orderBy:’action'”>

<td>{{item.action}}</td>

<td><input type=”checkbox” ng-model=”item.done” /></td>

</tr>

</tbody>

Filtering can be applied to any part of the data model, and here you can see that I have used filters to control the data that is used by the ng-repeat directive that populates the table element with details of the to-do list items. I have used two filters: the filter filter (an annoying name for a useful component) and the orderBy filter.

The filter filter selects objects based on the criteria it is configured with. I have applied the filter such that it selects the items whose done property is false, which has the effect that any complete to-do item won’t be shown to the user. The orderBy filter sorts the data items, and I have used it to sort by the value of the action property.

I’ll explain filters in detail in Chapter 14, but you can see the effect I have created by navigating the browser to the todo.html file, adding a new item, and then checking the Done box, as shown in Figure 2-9.

Tip Notice that when using the orderBy filter, I specify the property I want to use for sorting as a string literal value, between single quote characters. By default, AngularJS assumes that everything is a property defined by the scope and without the quote characters, would look for a scope property called action. This is helpful when you want to define values programmatically but does mean you have to remember to use literal values when you want to specify a constant.

When you add a new item, it will be inserted into the list based on alphabetical order, and when you check the box, the item will be hidden. (The data in the model isn’t sorted; the sort operation is performed when the ng-repeat directive is processed to create the rows in the table.)

1. Improving the Filter

The previous example demonstrates how the filter feature works, but the result is pretty useless because checked tasks are forever hidden from the user. Fortunately, it is a simple matter to create a custom filter, as shown in Listing 2-11.

Listing2-11. Creating a Custom Filter in the todo.html File

<script>

var model = {

user: “Adam”,

items: [{ action: “Buy Flowers”, done: false },

{ action: “Get Shoes”, done: false },

{ action: “Collect Tickets”, done: true },

{ action: “Call Joe”, done: false }],

};

var todoApp = angular.module(“todoApp”, []);

todoApp.filter(“checkedItems”, function () {

return function (items, showComplete) {

var resultArr = [];

angular.forEach(items, function (item) {

if (item.done == false || showComplete == true) {

resultArr.push(item);

}

});

return resultArr;

}

});

todoApp.controller(“ToDoCtrl”, function ($scope) {

$scope.todo = model;

// …statements omitted for brevity…

});

</script>

The filter method defined by the AngularJS module object is used to create a filter factory, which returns a function that is used to filter a set of data objects. Don’t worry about the factory part for the moment; it is enough to know that using the filter method requires passing in a function that returns a function that returns the filtered data. The name I have given my filter is checkedItems, and the function that does the actual filtering has two arguments:

return function (items, showComplete) {

The items argument will be provided by AngularJS and will be the set of objects that should be filtered. I will provide a value for the showComplete argument when I apply the filter, and it is used to determine whether tasks that have been marked as done will be included in the filtered data. You can see how I have applied the custom filter in Listing 2-12.

Listing 2-12. Applying a Custom Filter in the todo.html File

<div class=”panel”>

<div class=”input-group”>

<input class=”form-control” ng-model=”actionText” />

<span class=”input-group-btn”>

<button class=”btn btn-default”

ng-click=”addNewItem(actionText)”>Add</button>

</span>

</div>

<table class=”table table-striped”>

<thead>

<tr>

<th>Description</th>

<th>Done</th>

</tr>

</thead>

<tbody>

<tr ng-repeat=

“item in todo.items | checkedItems:showComplete | orderBy:,action,“>

<td>{{item.action}}</td>

<td><input type=”checkbox” ng-model=”item.done” /></td>

</tr>

</tbody>

</table>

<div class=”checkbox-inline”>

<label><input type=”checkbox” ng_model=”showComplete”> Show Complete</label> </div>

</div>

I have added a check box that uses the ng-model directive to set a model value called showComplete, which I pass to my custom filter through the ng-repeat directive in the table:

<tr ng-repeat=”item in todo.items | checkedItems:showComplete | orderBy:’action'”>

The syntax for custom filters is the same as for the built-in filtering support. I specify the name of the filter I created with the filter method, followed by a colon (:), followed by the name of the model property that I want to pass to the filter function. I have specified the showComplete model property, which means that the state of the check box will be used to control the visibility of the checked items. You can see the effect in Figure 2-10.

Source: Freeman Adam (2014), Pro AngularJS (Expert’s Voice in Web Development), Apress; 1st ed. edition.

Leave a Reply

Your email address will not be published. Required fields are marked *