left-icon

AngularJS Succinctly®
by Frederik Dietz

Previous
Chapter

of
A
A
A

CHAPTER 4

Filters

Filters


Angular Filters are typically used to format expressions in bindings in your template. They transform the input data into a new, formatted data type.

Formatting a String with a Currency Filter

Problem

You wish to format the amount of currency with a localized currency label.

Solution

Use the built-in currency filter and make sure you load the corresponding locale file for the user's language:

<html>
  <head>
    <meta charset='utf-8'>
    <script src="js/angular.js"></script>
    <script src="js/angular-locale_de.js"></script>
  </head>
  <body ng-app>
    <input type="text" ng-model="amount" placeholder="Enter amount"/>
    <p>Default Currency: {{ amount | currency }}</p>
    <p>Custom Currency: {{ amount | currency: "Euro" }}</p>
  </body>
</html>

Enter an amount and it will be displayed using Angular's default locale.

You can find the complete example on GitHub.

Discussion

In our example, we explicitly load the German locale settings and, therefore, the default formatting will be in German. The English locale is shipped by default so there's no need to include the angular-locale_en.js file. If you remove the script tag, you will see the formatting change to English instead. This means, in order for a localized application to work correctly, you need to load the corresponding locale file. All available locale files can be seen on GitHub.

Implementing a Custom Filter to Revert an Input String

Problem

You wish to revert a user's text input.

Solution

Implement a custom filter, which reverts the input:

<body ng-app="MyApp">
  <input type="text" ng-model="text" placeholder="Enter text"/>
  <p>Input: {{ text }}</p>
  <p>Filtered input: {{ text | reverse }}</p>
</body>

var app = angular.module("MyApp", []);

app.filter("reverse", function() {
  return function(input) {
    var result = "";
    input = input || "";
    for (var i=0; i<input.length; i++) {
      result = input.charAt(i) + result;
    }
    return result;
  };
});

You can find the complete example on GitHub.

Discussion

Angular's filter function expects a filter name and a function as params. The function must return the actual filter function where you implement the business logic. In this example, it will only have an input param. The result will be returned after the for loop has reversed the input.

Passing Configuration Params to Filters

Problem

You wish to make your filter customizable by introducing config params.

Solution

Angular filters can be passed as a hash of params which can be directly accessed in the filter function:

<body ng-app="MyApp">
  <input type="text" ng-model="text" placeholder="Enter text"/>
  <p>Input: {{ text }}</p>
  <p>Filtered input: {{ text | reverse: { suffix: "!"} }}</p>
</body>

var app = angular.module("MyApp", []);

app.filter("reverse", function() {
  return function(input, options) {
    input = input || "";
    var result = "";
    var suffix = options["suffix"] || "";

    for (var i=0; i<input.length; i++) {
      result = input.charAt(i) + result;
    }

    if (input.length > 0) result += suffix;

    return result;
  };
});

You can find the complete example on GitHub.

Discussion

The suffix ! is passed as an option to the filter function and is appended to the output. Note that we check if an actual input exists since we don't want to render the suffix without any input.

Filtering a List of DOM Nodes

Problem

You wish to filter a ul list of names.

Solution

In addition to  strings as input, Angular's filters also work with arrays:

<body ng-app="MyApp">
  <ul ng-init="names = ['Peter', 'Anton', 'John']">
    <li ng-repeat="name in names | exclude:'Peter' ">
      <span>{{name}}</span>
    </li>
  </ul>
</body>

var app = angular.module("MyApp", []);

app.filter("exclude", function() {
  return function(input, exclude) {
    var result = [];
    for (var i=0; i<input.length; i++) {
      if (input[i] !== exclude) {
        result.push(input[i]);
      }
    }

    return result;
  };
});

We pass Peter as the single param to the exclude filter, which will render all names except Peter.

You can find the complete example on GitHub.

Discussion

The filter implementation loops through all names and creates a result array excluding 'Peter'. Note that the actual syntax of the filter function didn't change at all from our previous example with the string input.

Chaining Filters Together

Problem

You wish to combine several filters to form a single result.

Solution

Filters can be chained using the Unix-like pipe syntax:

<body ng-app="MyApp">
  <ul ng-init="names = ['Peter', 'Anton', 'John']">
    <li ng-repeat="name in names | exclude:'Peter' | sortAscending ">
      <span>{{name}}</span>
    </li>
  </ul>
</body>

Discussion

The pipe symbol (|) is used to chain multiple filters together. First, we will start with the initial array of names. After applying the exclude filter, the array contains only ['Anton', 'John'] and afterwards we will sort the names in ascending order.

I leave the implementation of the sortAscending filter as an exercise to the reader.

Testing Filters

Problem

You wish to unit test your new filter. Let us start with an easy filter, which renders a checkmark depending on a Boolean value:

<body ng-init="data = true">
  <p>{{ data | checkmark}}</p>
  <p>{{ !data | checkmark}}</p>
</body>

var app = angular.module("MyApp", []);

app.filter('checkmark', function() {
  return function(input) {
    return input ? '\u2713' : '\u2718';
  };
});

Solution

Use the angular-seed project as a bootstrap again:

describe('MyApp Tabs', function() {
  beforeEach(module('MyApp'));

  describe('checkmark', function() {
     it('should convert boolean values to unicode checkmark or cross',
        inject(function(checkmarkFilter) {
       expect(checkmarkFilter(true)).toBe('\u2713');
       expect(checkmarkFilter(false)).toBe('\u2718');
     }));
   });
});

Discussion

The beforeEach loads the module and the it method injects the filter function for us. Note that it has to be called checkmarkFilter; otherwise, Angular can't inject our filter function correctly.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.