Angular Filters using TypeScript


This is part of a blog series – please read the intro part and install the prerequisites if you want to follow along.

Using built-in filters

A filter can either format/convert the data in some way (similar to a XAML converter). Some built-in filters that work like this are number, currency, date, lowercase and uppercase.

To make all the store names uppercase in the store listing for example, you would add the uppercase filter to the store.Name binding in storeListView.html

<h4>{{store.Name | uppercase }}</h4>

Some of the built-in filters work on lists, like limitTo, orderBy or filter.  We want our stores sorted by name a-z, so let’s use the orderBy filter to sort the stores.

ng-repeat="store in vm.stores | orderBy: 'Name'"

You can also chain filters, so if you wanted to order by name and then limit the results to just two stores, you would add another filter like this

ng-repeat="store in vm.stores | orderBy: 'Name' | limitTo: 2"

Creating a custom filter

In this post we’re going to create our own custom filter to search for certain stores. (Technically we could probably have used the built-in filter-filter, but what’s the fun in that 🙂 )

Add the markup

I have already prepared the markup a little bit by binding the input text box to the ng-model store.search

<input class="input-lg" ng-model="store.search" placeholder="search for a store" />

store.search doesn’t exist, I just made it up. We could have called it unclebob or anything really, as long as we use the same ng-model in the filter markup.

We’ll call our new filter storeSearch and pass it the parameter store.search from above like this

ng-repeat="store in vm.stores | orderBy: 'Name' | storeSearch : store.search"

The list of stores (vm.stores) are passed in automatically to the storeSearch filter and in this case because of the orderBy they are also ordered by Name.

Create the filter

Create a new StoreSearchFilter.ts in the app/stores and add the following content

module app.filters {
    export function StoreSearch() {
        return function (items: app.domain.IStore[], search: string): app.domain.IStore[] {
            var filtered = [];
            if (!search) { return items; }
            angular.forEach(items, function (item) {

                if (angular.lowercase(item.Name).indexOf(angular.lowercase(search)) != -1) {
                    filtered.push(item);
                }

            });
            return filtered;
        }
    }
    angular.module("mallApp").filter("storeSearch", StoreSearch);
}

When we work with filters, we don’t export them as classes but rather as functions.  In this case, the list of stores is passed down to the function along with the string from the input box.  Actually, the list of stores is even sorted by name since we applied the orderBy filter first.

We go through all the stores and return a list with the stores that have a name that contains the string we’re searching for.

Finally we register the filter with the mallApp module.

Include the scripts in index.html

As with all other components, the html page won’t know anything about the filter unless we include the scripts so let’s do that.

<!-- filters and directives -->
<script src="app/stores/StoreSearchFilter.js"></script>

Browse and test

Try entering different search texts in the input box. If everything works as it should the list of stores should be filtered by your search text.

We are almost finished now… but it would be nice to show some store details if you click on one of the stores, and for that we need to look into routing.  That will be the topic for the next post.

Next: Routing

Comments (1)

  1. Craig says:

    How would you express angular dependencies on your TypeScript filter? I would then expect that the filter will become a class with static $inject and a constructor

Skip to main content