How to filter a list in AngularDart

A common pattern when showing a list on a website is allowing the users to filter it with a search term. So, how do you do this in AngularDart?

In this code tutorial, which uses AngularDart 5.0, we will create a simple web app with a list. Above the list, in a sibling component of the list, we will show an input field and a clear button. As the user types in the input, the list is filtered accordingly. If the user taps the clear button, all the items of the list are shown again and the input field is cleared.

The code is available on github.

Disclaimer: I am new to AngularDart and web apps in general,  but I am proficient with Dart. I started using AngularDart a few weeks ago for my 2 job boards, Flutter Jobs and Flexible Tech Jobs in the UK. I am a mobile app developer and used the official online documentation to create those web apps. I have written this tutorial because I struggled to find AngularDart code tutorials. AngularJS tutorials are plentiful, but I’m not proficient with JS and I cannot “translate” from AngularJS to AngularDart easily.

Setting up the web app

Create a web app called AngularDartFilterList. If you’re not sure how to do this, refer to the official doc. By default, an app with a to do list is created.

Firstly, we remove the todo_list folder under lib/src.

Secondly, we create a list folder under lib/src, and add 3 new files to it, for the list component. The files are list_component.css, list_component.dart, and list_component.html.

Thirdly, we create the ListComponent in list_component.dart.

 

The html in list_component.html is a placeholder for now.

 

Lastly, we amend app_component.dart and app_component.html to use the ListComponent instead of the TodoListComponent.

 

Getting the list data

In a real app, you would load the data from a backend, using a Service. So we are using the same general architecture here.

However, for simplicity, we use Future.delayed() to simulate a server call, and the data will instead be hardcoded in the Service class.

We start off with creating a new data folder under lib/src. In it, we create item.dart and items_service.dart.

The first file is a basic model for Item, as below.

 

The second file is a service to get and store in memory the list of items. For the list of items, I took inspiration from the books I have recently read. You may put your own favourite authors in there 😉

Note: We return the cached items if available. In a real world web app, depending on the domain of your web app, you may want to either invalidate the cache after x minutes (eg for a small merchandise store), or use a backend with server side events functionality such as Firebase (eg for a chat app).

We could directly inject the Service into ListComponent. However,  in a real web app, you may have other components that need access to the items. So we inject it in the AppComponent, the parent of all components, and then access that instance from the ListComponent.

 

Displaying the list

We load the list of items in the component, so we can refer to it from the template.

We can now use items in the template. We combine it with *ngIf and *ngFor to implement 3 different UI states: “loading”, list of items, and “empty list”. So let’s replace the placeholder div list_component.html with the code below.

 

Finally, we apply a little bit of styling, in list_component.css. This tutorial isn’t about styling, so we keep it simple.

 

Adding a user input field

We could add the user input field to the ListComponent. However, for a more complex UI, it would really bloat the ListComponent. Therefore, we use the architecture pattern of “a component per functionality”.  The ListComponent shows a list of items, and the FilterComponent enables the user to specify what they are searching for.

We start with creating a filter folder under lib/src, and add 3 new files to it, for the filter component. The files are filter_component.css, filter_component.dart, and filter_component.html.

Then, we create the FilterComponent in filter_component.dart.

 

The html in filter_component.html is an input field. As the user types, searchUpdated(String value) gets fired.

 

We then amend app_component.dart and app_component.html to show the FilterComponent above the ListComponent.

 

 

Lastly, we style the user input in filter_component.css. This tutorial isn’t about styling, so we keep it simple.

Interaction between FilterComponent and ListComponent

To communicate between ListComponent and FilterComponent, which are siblings and not parent/child, we will use a broadcast stream in a service. The service will be injected into the parent of both siblings, so the siblings can access it. The ListComponent will subscribe to the event stream. Each time the input value changes, the current input value is added to the stream.

We start with creating filter_service.dart in lib/src/filter. It has a broadcast stream of strings, corresponding to the value in the user input field.

 

Then, we inject it in app_component.dart.

 

Now that it is injected in AppCompoment, we can access it in the 2 child components, FilterCompoment and ListComponent. In FilterCompoment, we add an event to the Stream each time the input field value is updated; in ListCompoment, we listen to the stream.

 

 

Filtering the list data

We now add the filter string as an argument to the getItems() method in ItemsService, and create an internal method to filter the cached list of items.

 

We can now call this new method from ListCompoment.

 

Clearing the user input

To allow the user to clear the input field, we add an image. On click, we both clear the UI and notify FilterCompoment that the new value for the filter is an empty string.

Download  cancel_icon.png and save it in web folder. Now, we can amend the FilterCompoment template to include it.

 

Lastly, we style the clear image in filter_component.css. This tutorial isn’t about styling, so we keep it simple.

Voila!

Screenshot
Screenshot

What next?

In this tutorial, we mocked getting the data. For more information on actually getting data from a server, check out the official doc on fetching data dynamically.

Author: Natalie Masse Hooper

Mobile app developer with 14 years experience. Started with the Android SDK in 2010 and switched to Flutter in 2017. Past apps range from start ups to large tech (Google) and non tech (British Airways) companies, in various sectors (transport, commercial operations, e-commerce).

Leave a Reply

Your email address will not be published.