Using Filters with AngularJS: Filtering Single Data Values

AngularJS comes with two kinds of built-in filters: those that operate on single values and those that operate on collections. I am going to start with those that work on a single value because they are the easiest to work with and provide a gentle introduction to the world of filters. I have listed the single-value filters in Table 14-3. I describe each of these filters in the sections that follow.

Tip One of the most useful things you can do with filters is chain them together so that multiple filters operate in sequence on the same data. I am going to demonstrate how the built-in filters work—especially those that operate on collections—before demonstrating how this feature works. See the “Chaining Filters” section later in the chapter for a demonstration.

1. Formatting Currency Values

The currency filter formats numeric values so they represent currency amounts—so that 1.2, for example, becomes $1.20. You can see how I have applied the currency filter to the Price column in the example table in Listing 14-2.

Listing 14-2. Applying the currency Filter in the filters.html File

<tr ng-repeat=”p in products”>

<td>{{p.name}}</td>

<td>{{p.category}}</td>

<td>{{p.expiry}}</td>

<td class=”text-right”>{{p.price | currency}}</td>

</tr>

You can see how easy it is to apply the filter to the data binding. I append the bar symbol (the | character) to the binding source (p.price in this case) followed by the filter name. This is the way that all filters are applied, and you can see the effect in Figure 14-2.

The numeric value is adjusted and rounded to show two decimal places and prefixed with the currency symbol. The default currency symbol is $, but you can specify an alternative, as shown in Listing 14-3.

Listing 14-3. Using a Different Symbol for the currency Filter in the filters.html File

<tr ng-repeat=”p in products’^

<td>{{p.name}}</td>

<td>{{p.category}}</td>

<td>{{p.expiry}}</td>

<td class=”text-right”>{{p.price | currency:”£” }}</td>

</tr>

I have followed the name of the filter with a colon (the : character) and then the symbol I want expressed as a literal string. This example uses the symbol for the British pound, and you can see the effect in Figure 14-3.

2. Formatting Other Numeric Values

The number filter formats numeric data values to fix the number of decimal places displayed, rounding the value as required. You can see how I have used the number filter to display only whole-dollar amounts in the Price column of the example table in Listing 14-4.

Listing 14-4. Applying the number Filter in the filters.html File

<tr ng-repeat=”p in products”>

<td>{{p.name}}</td>

<td>{{p.category}}</td>

<td>{{p.expiry}}</td>

<td class=”text-right”>${{p.price | number:0 }}</td>

</tr>

I apply the filter using the bar character and the filter name, followed by a colon and then the number of decimal places I want to display. I have specified zero decimal places, which creates the effect shown in Figure 14-4.

3. Formatting Dates

The date filter formats dates, which can be expressed as strings, JavaScript Date objects, or numbers of milliseconds. To demonstrate the use of the date filter, I have added a behavior to the controller in the example that returns a Date object, which is a number of days into the future. I then used this behavior to prepare the expiry property of each data object for use with the date filter, as shown in Listing 14-5.

Listing 14-5. Using the date Filter in the filters.html File

<html ng-app=”exampleApp”>

<head>

<title>Filters</title>

<script src=”angular.js”></script>

<link href=”bootstrap.css” rel=”stylesheet” />

<link href=”bootstrap-theme.css” rel=”stylesheet” />

<script>

angular.module(“exampleApp”, [])

.controller(“defaultCtrl”, function ($scope) {

$scope.products = [

{ name: “Apples”, category: “Fruit”, price: 1.20, expiry: 10 },

{ name: “Bananas”, category: “Fruit”, price: 2.42, expiry: 7 },

{ name: “Pears”, category: “Fruit”, price: 2.02, expiry: 6 },

// …other data objects omitted for brevity…

];

$scope.getExpiryDate = function (days) {

var now = new Date();

return now.setDate(now.getDate() + days);

}

});

</script>

</head>

<body ng-controller=”defaultCtrl”>

<div class=”panel panel-default”>

<div class=”panel-heading”>

<h3>

Products

<span class=”label label-primary”>{{products.length}}</span>

</h3>

</div>

<div class=”panel-body”>

<table class=”table table-striped table-bordered table-condensed”>

<thead>

<tr>

<td>Name</td><td>Category</td>

<td>Expiry</td><td class=”text-right”>Price</td>

</tr>

</thead>

<tbody>

<tr ng-repeat=”p in products”>

<td>{{p.name}}</td>

<td>{{p.category}}</td>

<td>{{getExpiryDate(p.expiry) \ date:”dd MMM yy”}}</td>

<td class=”text-right”>${{p.price | number:0 }}</td>

</tr>

</tbody>

</table>

</div>

</div>

</body>

</html>

To use the filter, I specify date, followed by a colon, followed by a formatting string that consists of the date components you want to display. In the listing I have used three date components in my formatting string: d, MMM, and yy. I have listed the full set of date components in Table 14-4.

You can see from the table that the formatting string I used in the listing produces a date like 05 Mar 15, and you can see the effect on the product table in Figure 14-5.

4. Changing String Case

The uppercase and lowercase filters transform strings so that the characters are all uppercase or lowercase. I don’t often use the uppercase filter, but I find that the lowercase filter is useful for mapping between strings that are capitalized for display in the HTML layout and property names. In Listing 14-6, you can see how I have applied the uppercase filter to the Name column and the lowercase to the Category column in the example. There are no configuration options for these filters.

Listing 14-6. Applying the uppercase and lowercase Filters in the filters.html File

<tr ng-repeat=”p in products”>

<td>{{p.name \ uppercase }}</td>

<td>{{p.category \ lowercase }}</td>

<td>{{getExpiryDate(p.expiry) | date:”dd MMM yy”}}</td>

<td class=”text-right”>${{p.price | number:0 }}</td>

</tr>

These filters do exactly what you would expect, and you can see the result of these changes in Figure 14-6.

5. Generating JSON

The json filter creates a JSON string from a JavaScript object. I have included this filter for completeness, but it is one that I have never found a use for, given how easy it is to work with JSON data in JavaScript anyway. In Listing 14-7, you can see how I have changed the ng-repeat directive in the example to include a JSON representation of each data object.

Listing 14-7. Applying the json Filter in the filters.html File

<tr ng-repeat=”p in products”>

<td colspan=”4″>{{p \ json}}</td>

</tr>

I replaced the original table cells with one that spans all of the columns and contains the data object, filtered by the json filter. You can see the result in Figure 14-7.

6. Localizing Filter Output

The currency, number, and date filters all have support for formatting values using localization rules, which are defined in localization files such as the one that I downloaded at the start of the chapter. You can see how I have used the localization file to generate localized formatting in Listing 14-8.

Listing 14-8. Using Localized Filter Formatting in the filters.html File

<html ng-app=”exampleApp”>

<head>

<title>Filters</title>

<script src=”angular.js”></script>

<script src=”angular-locale_fr-fr.js”></script>

<link href=”bootstrap.css” rel=”stylesheet” />

<link href=”bootstrap-theme.css” rel=”stylesheet” />

<script>

angular.module(“exampleApp”, [])

.controller(“defaultCtrl”, function ($scope) {

$scope.products = [

{ name: “Apples”, category: “Fruit”, price: 1.20, expiry: 10 },

{ name: “Bananas”, category: “Fruit”, price: 2.42, expiry: 7 },

{ name: “Pears”, category: “Fruit”, price: 2.02, expiry: 6 },

{ name: “Tuna”, category: “Fish”, price: 20.45, expiry: 3 },

{ name: “Salmon”, category: “Fish”, price: 17.93, expiry: 2 },

{ name: “Trout”, category: “Fish”, price: 12.93, expiry: 4 },

{ name: “Beer”, category: “Drinks”, price: 2.99, expiry: 365 },

{ name: “Wine”, category: “Drinks”, price: 8.99, expiry: 365 },

{ name: “Whiskey”, category: “Drinks”, price: 45.99, expiry: 365 }

];

$scope.getExpiryDate = function (days) {

var now = new Date();

return now.setDate(now.getDate() + days);

}

});

</script>

</head>

<body ng-controller=”defaultCtrl”>

<div class=”panel panel-default”>

<div class=”panel-heading”>

<h3>

Products

<span class=”label label-primary”>{{products.length}}</span>

</h3>

</div>

<div class=”panel-body”>

<table class=”table table-striped table-bordered table-condensed”>

<thead>

<tr>

<td>Name</td>

<td>Category</td>

<td>Expiry</td>

<td class=”text-right”>Price</td>

</tr>

</thead>

<tbody>

<tr ng-repeat=”p in products”>

<td>{{p.name}}</td>

<td>{{p.category}}</td>

<td>{{getExpiryDate(p.expiry) | date:”shortDate”}}</td>

<td class=”text-right”>{{p.price | currency }}</td>

</tr>

</tbody>

</table>

</div>

</div>

</body>

</html>

I have added a script element to import the angular-locale_fr-fr.js file into the HTML document and restored the table cells for the individual model object properties. The name and category properties are not filtered, but I have used the date and currency filters for the expiry and price properties, respectively.

Notice that I have specified shortDate for the date filter formatting string. This is one of a number of shortcut formats that the date filter supports for common date expressions. Table 14-5 shows the complete set of these shortcuts. The output generated by these shortcuts is, of course, locale-specific, but I have shown the equivalent format string for the en-US locale, which represents English as used in the United States.

In Figure 14-8, I show some of the table rows with and without the script element for the angular-locale_fr-fr.js file so that you can see the impact of using localized formatting.

There are some obvious differences between the formatting in the default and fr-fr locales: The order of the month and day is reversed, the currency symbol and position have changed, and a comma is used to separate the whole and fractional elements of the numbers (3,41 rather than 3.41).

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 *