AngularJS List Filters

Lists are useful for repeatedly displaying large amounts of data, and list filters let you manipulate list items later. This article explains how to combine them to display data.

Repeating Lists

Web pages that handle data often display large amounts of data in the same format, such as in tables.

In such cases, there is a structure that repeats the same display. In other words, once you specify “write data in this format,” the system outputs each item in the same repeated format when data is passed in.

AngularJS has something called a “list.” It is a structure that takes values in order from something organized as an array and processes them. It can be used easily just by adding an attribute to HTML.

Let us explain while creating an example. First, write the script and save it as script.js.

var myapp = angular.module('myapp',[]);
var helo = myapp.controller('HeloController',
    function(){
        this.count = 0;
        this.data = [
            {id:0,name:'no data',price:0,get:false},
            {id:1,name:'Android phone',price:7800,get:true},
            {id:2,name:'New iPhone',price:549020,get:false},
            {id:3,name:'windows phone',price:38765,get:true}
        ];
    }
);

Here, a controller named HeloController stores data with items such as id, name, price, and get in a variable named data as an array. We will display this data as a list.

How ng-repeat Works

Next, write the HTML. The example is as follows.

<!DOCTYPE html>
<html>
<head>
    <title>AngularJS Sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script src="script.js"></script>
    <style>
    body { color:gray; }
    h1 { font-size:18pt; font-weight:bold; }
    span.label { display:inline-block;width:50px; color:red; }
    input { width:100px; }
    .msg { font-size:14pt; font-weight:bold;color:gray; }
    th { color:#eee; background-color:#999; padding: 5px 10px;}
    td { color:#333; background-color:#ddd; padding: 5px 10px;}
    </style>
</head>
<body ng-app="myapp" ng-init="num=0">
    <h1>Data Display</h1>
    <div ng-controller="HeloController as ctl">

    <table>
    <tr><th>ID</th><th>NAME</th><th>PRICE</th><th>GET?</th></tr>
    <tr ng-repeat="obj in ctl.data">
        <td>{{obj.id}}</td>
        <td>{{obj.name}}</td>
        <td>{{obj.price | currency:"₩"}}</td>
        <td>{{obj.get}}</td>
    </tr>
    </table>
     
    </div>
</body>
</html>

Write it like this and display it in the browser. The data in data appears as a table.

The table display is handled in this part.

<table >
  <tr><th>...omitted...</th></tr>
  <tr ng-repeat="obj in ctl.data">
    <td>{{obj.id}}</td>
    <td>{{obj.name}}</td>
    <td>{{obj.price | currency:"₩"}}</td>
    <td>{{obj.get }}</td>
  </tr>
</table>

There is nothing special about <table>. The key is the <tr> tag. Here, an attribute, or directive, for repeating with a list is written as follows.

ng-repeat="variable in array"

ng-repeat takes values from the prepared array, sets each one to the variable, and outputs the tag where ng-repeat is written. That is, the tag containing ng-repeat is output repeatedly as many times as there are values in the array. Looking at the <td> tag inside <tr>:

<td>{{obj.id}}</td>

It outputs by specifying a property of the variable object obj obtained from the array. If objects are organized in an array, values inside each object can be handled freely like this.

List Filters

We saw that repeatedly displaying multiple data items is easy with lists. These lists do more than simply display the contents of an array in order. You can manipulate various data when displaying them.

For example, change the <tr> tag from the previous example as follows.

<tr ng-repeat = "obj in ctl.data
    | orderBy : '-price' ">

This sorts and displays the data in order from the largest price value.

Here, after obj in ctl.data, the | symbol is added, followed by orderBy : '-price'. This is a list filter applied to the list. We previously explained filters used when displaying text, and a list filter can be considered the list version of that. It can manipulate the items and order displayed in a list.

Now let us explain the filters that can be used for repeated display.

Specifying Sort Order

orderBy : itemName

This is the one used in the previous example. It sorts the array using the specified item. Specify the item name after the colon. If you add a minus sign before the name, it sorts in reverse order. For example, specifying price sorts from the smallest price, while -price sorts from the largest price.

Specifying the Maximum Number of Items

limitTo: integer

This specifies the number of array items. For example, limitTo:5 extracts the first five items. If you specify it with a minus sign, such as limitTo:-5, it extracts the last five items.

Value Comparison

filter: pattern

This is used to extract only specific items with a regular expression pattern. This was also used as a text filter. In the case of a list, only list items that match the pattern are extracted and processed. For example, specifying filter:'ok' displays only items with the value ok.

Custom List Filters

There are not many list filters provided by default. Still, because regular expressions can be used, you may think that “most things are possible if you write a pattern.” However, specifying regular expression patterns in many ways is not always easy to use.

Also, when complex structured objects rather than simple values are organized in an array, you need a filter that extracts and checks the necessary values depending on the object.

In such cases, you can add and use filters. Not only text filters but also list filters can be created directly. They are created as follows.

controller.filter(name, function);

This is the same as a text filter. However, the prepared function is a little different.

function() {
  return function(argument) {
    ... manipulate the argument array ...
    return array;
  }
}

The function returns another function. The returned function is the processing executed as the filter.

The filter function prepares one argument. The data array is passed to it. Based on this array, create a new array and return it. Then ng-repeat runs based on that returned array. In other words, you only need to think about how to create the new array.

Creating a List Filter

Let us create a simple list filter and use it in an example script. Write and save script.js as follows.

var myapp = angular.module('myapp',[]);
var helo = myapp.controller('HeloController',
    function() {
        this.count = 0;
        this.data = [
            { id:0, name:'no data',price:0,get:false },
            { id:1, name:'Android phone', price:7800, get:true },
            { id:2, name:'New iPhone', price:549020, get:true },
            { id:3, name:'windows phone', price:38765, get:true },
            { id:4, name:'firefox phone', price:14370, get:true },
            { id:5, name:'blackberry phone', price:-123, get:false },
        ];
        this.getData = function() {
            return this.data[this.count].id + ': ' + 
                this.data[this.count].name + ', ' + 
                this.data[this.count].price + '.';
        };
    }
);
 
// Check get and return only true items.
helo.filter('getRepeat', 
    function() {
        return function(items) {
            var res = [];
            angular.forEach(items,function(item) {
                if (item.get)
                    res.push(item);
            });
            return res;
        };
    }
);

This time, a list filter named getRepeat is created in the HeloController controller. The returned function in the filter looks like this.

function (items) {
  var res = [];
  angular.forEach (items, function (item) {
    if (item.get)
        res.push (item);
  });
  return res;
};

Here, from the items passed as an argument, only the items whose get value is true are collected into an array and returned. To repeat over the array, it uses forEach from the angular object.

angular.forEach(array, function);

This forEach gets elements in order from the first argument array and executes the second argument function. The obtained element is passed to the function as an argument. The function can use this argument to process every element of the array.

Using the Custom Filter

Now let us use the getRepeat filter we created. Write the HTML file as follows.

<!DOCTYPE html>
<html>
<head>
    <title>AngularJS Sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script src="script.js"></script>
    <style>
    body { color:gray; }
    h1 { font-size:18pt; font-weight:bold; }
    span.label { display:inline-block;width:50px; color:red; }
    input { width:100px; }
    .msg { font-size:14pt; font-weight:bold;color:gray; }
    th { color:#eee; background-color:#999; padding: 5px 10px;}
    td { color:#333; background-color:#ddd; padding: 5px 10px;}
    </style>
</head>
<body ng-app="myapp" ng-init="num=0">
    <h1>Data Display</h1>
    <p>Please enter text.</p>
    <div ng-controller="HeloController as ctl">
     
    <div class="input">
        <span class="label">Search:</span>
        <input type="text" ng-model="fstr">
    </div>
    <p class="msg">{{ctl.getData()} }</p>
    <hr/>
    
    <table>
    <tr><th>ID</th><th>NAME</th><th>PRICE</th><th>GET?</th></tr>
    <tr ng-repeat="obj in ctl.data | filter:fstr | orderBy : '-price' | getRepeat">
        <td>{{obj.id}}</td>
        <td>{{obj.name}}</td>
        <td>{{obj.price | currency:"₩"}}</td>
        <td>{{obj.get}}</td>
    </tr>
    </table>
     
    </div>
</body>
</html>

This time, in addition to the getRepeat filter, a filter that searches using text is also added. When you open the HTML file, only data whose GET? value is true appears in the table. This is the result of the getRepeat filter.

After confirming the display, enter some text in the Search field. Then only items that contain that text are displayed. This is processing using the filter filter. With filter, data can be searched easily.

Looking at the ng-repeat part of the <tr> tag, it is written as follows.

ng-repeat="obj in ctl.data | filter:fstr | orderBy : '-price' | getRepeat"
  • obj in ctl.data: Repeatedly extracts values from the ctl.data array and assigns them to obj.
  • filter:fstr: Checks whether the text includes fstr.
  • orderBy : ‘-price’: Sorts by price in descending order.
  • getRepeat: Displays only items whose get value is true.

In this way, four values are combined. The first obj in ctl.data performs the repeat processing, and the three list filters manipulate the contents of the array. This includes search, sorting, and getRepeat.

List filters, like text filters, are easier to create than they may look once you try them. Lists and list filters are essential features when displaying data. Be sure to understand them here.