Tutorial

Building Custom AngularJS Filters

Draft updated on Invalid Date
Default avatar

By Ado Kukic

Building Custom AngularJS Filters

This tutorial is out of date and no longer maintained.

Introduction

Not too long ago we took a look at some of the built-in Angular filters. The built-in filters cover many common use cases including formatting dates, currencies, limiting the number of items displayed, and more. These filters are both useful and give insights into how we may improve our workflow when building Angular apps.

Today, we will build our own custom AngularJS filters. We’ll start simple and build a couple of filters that manipulate numbers and strings, then we’ll build a filter that manipulates an entire data set. Finally, in our previous article where we discussed the built-in AngularJS filters, Pierre-Adrien asked how we could use the built-in Angular currency filter to display the currency denomination after the amount (i.e., “9.99$” instead of “$9.99”) as is common in some places of the world. Unfortunately, the built-in currency filter does not support this functionality, so we’ll build our own that does!

Anatomy of an Angular Filter

Angular exposes a simple API for creating a filter. Just as you would declare a controller with app.controller(‘myCtrl', function(){});, you can create a new filter by appending .filter(‘filterName', function(){}) to your Angular app.

A filter is very similar to a factory or service in many regards but has the added advantage of behaving on a global scope once created. As we have previously seen, you can invoke a filter on both the data binding in your HTML or directly inside of your controller or directive by using the $filter service. Let’s break down the structure of a filter.

    // To declare a filter we pass in two parameters to app.filter

    // The first parameter is the name of the filter
    // second is a function that will return another function that does the actual work of the filter

    app.filter('myFilter', function() {

      // In the return function, we must pass in a single parameter which will be the data we will work on.
      // We have the ability to support multiple other parameters that can be passed into the filter optionally
      return function(input, optional1, optional2) {

        var output;

        // Do filter work here

        return output;

      }

    });

This may seem confusing from the get-go, so let’s jump to some examples that will demystify writing custom filters.

Our First Custom Filter

Let’s start off slow and simple. The first custom filter we’ll write will convert numbers to their ordinal values, meaning that if we apply our ordinal filter to say the number 43, what will be displayed is “43rd”. Let’s look at the code for our ordinal filter.

    // Setup the filter
    app.filter('ordinal', function() {

      // Create the return function
      // set the required parameter name to **number**
      return function(number) {

        // Ensure that the passed in data is a number
        if(isNaN(number) || number < 1) {

          // If the data is not a number or is less than one (thus not having a cardinal value) return it unmodified.
          return number;

        } else {

          // If the data we are applying the filter to is a number, perform the actions to check its ordinal suffix and apply it.

          var lastDigit = number % 10;

          if(lastDigit === 1) {
            return number + 'st'
          } else if(lastDigit === 2) {
            return number + 'nd'
          } else if (lastDigit === 3) {
            return number + 'rd'
          } else if (lastDigit > 3) {
            return number + 'th'
          }

        }
      }
    });

Applying this filter to our views is straightforward:

    {{ 25 | ordinal }}

will yield 25th. If we were to apply the ordinal filter to a string, such as

    {{ 'not a number' | ordinal }}

we would simply get the string not a number back.

It is a good practice to ensure you have appropriate data to filter, and if you do not simply return the unmodified data back. Take a look at the CodePen below for some additional examples.

See the Pen AngularJS Custom Filter - Ordinal Numbers.

Capitalizing on Custom Filters

Sorry for the bad joke. The next custom filter we build will capitalize either the first letter or a letter we specify. The additional parameter will specify which letter to capitalize, if no additional parameter is passed then the first letter will be capitalized.

This is a bit of a contrived example and has no real practical uses but we’ll use it to show off how you could extend your filters.

    // Setup the filter
    app.filter('capitalize', function() {

      // Create the return function and set the required parameter as well as an optional parameter
      return function(input, char) {

        if (isNaN(input)) {

          // If the input data is not a number, perform the operations to capitalize the correct letter.
          var char = char - 1 || 0;
          var letter = input.charAt(char).toUpperCase();
          var out = [];

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

            if (i == char) {
              out.push(letter);
            } else {
              out.push(input[i]);
            }

          }

          return out.join('');

        } else {
          return input;
        }

      }

    });

Again, applying this filter is very simple. If we wanted to capitalize a specific letter, we could pass the optional parameter such as:

    {{ 'onomatopoeia' | capitalize:3 }}

and this would return the result of

Output
onOmatopoeia

See the Pen AngularJS Custom Filter - Capitalize.

Filters That Actually Filter

In the previous examples, we applied filters to single items, now let’s apply a filter to a collection. In this example, we will actually filter a data set.

In programming, there are hundreds of ways to reach the end goal, and in this example what we’ll filter a list and return only the items that match certain criteria.

We will go through a list of programming languages and display only the statically typed ones. Easy enough right?

    // Setup the filter
    app.filter('staticLanguage', function() {

      // Create the return function and set the required parameter name to **input**
      return function(input) {

        var out = [];

        // Using the angular.forEach method, go through the array of data and perform the operation of figuring out if the language is statically or dynamically typed.
        angular.forEach(input, function(language) {

          if (language.type === 'static') {
            out.push(language)
          }

        })

        return out;
      }

    });

See the Pen AngularJS Custom Filter - Static Language.

Custom Currencies

In the first example, we looked at creating a simple custom filter that only did one thing (and hopefully did that one thing well). Next, let’s take a look at how we can create a filter that accepts additional parameters.

The idea for this filter comes from Pierre Adrian who was wondering whether the built-in currency filter supports the ability to choose what side the currency symbol goes on. Unfortunately, it does not, so we’ll build our own custom currency filter that does!

In the US it is standard practice to place the $ symbol before the amount (i.e. $9.99), but in certain countries, it is customary to place the symbol after the amount (i.e 9.99$).

For our custom filter, we will allow the user to pass two parameters. The first will be the symbol or string they want to use to denote the currency, and the second a true or false boolean value that will determine whether the symbol is added before or after the amount.

We will default the symbol to the dollar sign ($) and the position to before of the amount so that if those aren’t passed the filter still works.

    // Setup the filter
    app.filter('customCurrency', function() {

      // Create the return function and set the required parameter name to **input**
      // setup optional parameters for the currency symbol and location (left or right of the amount)
      return function(input, symbol, place) {

        // Ensure that we are working with a number
        if(isNaN(input)) {
          return input;
        } else {

          // Check if optional parameters are passed, if not, use the defaults
          var symbol = symbol || '$';
          var place = place === undefined ? true : place;

          // Perform the operation to set the symbol in the right location
          if( place === true) {
            return symbol + input;
          } else {
            return input + symbol;
          }

        }
      }

    });

One thing to note when dealing with filters that support multiple parameters: you must pass the parameters in the correct order! You do not have to pass all the parameters, so in our custom currency filter it is perfectly acceptable to pass only the symbol, but you cannot only pass the location of where you want the symbol to display.

If you wanted to change only the order, you would still need to pass in the symbol such as {{ 25 | customCurrency:'$':false }}.

See the Pen AngularJS Custom Filter - Custom Currency.

Conclusion

Today we built our own custom AngularJS filters. We learned how to create filters from scratch, built filters that did single tasks, and created filters that had extended functionality. Filters can be a powerful tool for extending the presentation of your applications. What are some custom filters you would like to see?

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Ado Kukic

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel