Sorting Tables in Angular with RxJS

Use observables to work with constantly changing data!

Dewaun Ayers
Dev Genius

--

I am working on a University assignment to build a site in Angular using Australian Football League (AFL) data from the Squiggle API (api.squiggle.com) and one of the user stories asked me to show a list of predictions that your team will win. So, naturally I built a table. Being the overachiever I am, I wondered, “Is it possible to sort a few of the columns in the table?” Well, the answer was obviously yes. But was it an easy task?

Heck. NO.

Coming from a primarily React background, I tried to take a very React approach and that failed considerably. So, I turned to Google and boy was I unhappy. There were a lot of solutions out there but they were all for older versions of Angular. So, after a bit of time (and maybe some tears) making my way through the docs I figured it out and wanted to share it here with you all.

Before I get into this:

If you are an Angular developer PLEASE give feedback! For the sake of being honest with myself I won’t use any of it until after I submit my assignment but I will take it into account afterwards and implement any improvements. :)

ALSO… This is just my understanding of how these pieces fit together. Don’t just take my word for it! Checkout the docs at angular.io and learnrxjs.io!

Now onto the main show…

First let’s get the latest Angular CLI:

npm install -g @angular/cli

Next we want to create a simple project to test this out in using the ng CLI command:

ng new table-sorter-app

After that cd into your project and create a new component:

ng generate component table

We will be doing all of our work in the table.component.[ts|html] files. For the most part I will be talking mostly about the TypeScript side of things. I assume you can make your own table so will only show a basic snippet of the HTML code.

Let’s take a look at what’s table.component.ts will look like

Breaking this down we will be using BehaviorSubject, combineLatest, Observable, and of from rxjs as well as map and scan from rxjs/operators

We set our table$ variable as an Observable so that we can easily update our HTML if the table data changes. This is good for when you have some data coming from a live feed or just some random API.

We use BehaviorSubject as an event emitter to update the sorting of the table whenever the sortableColumn$ observable changes value.

sortDirections$ is another observable that pipes sortableColumn$ and uses scan as a reducer to return the correct sortConfig whenever sortableColumn$ changes.

In the constructor we just need to set table$ to something in order to stop TypeScript from complaining. You can do this in a more meaningful way, but for the sake of this tutorial it works just fine.

In the ngOnInit method combineLatest is used to combine the table data and sortDirection$ observables. We wrap table in of to convert it to an observable sequence. This way whenever either values changes it will update the table$ observable as mentioned before. We use combineLatest.pipe() to apply the sort function to the table data effectively sorting it on each update. Finally we subscribe to the sortDirections$ observable and update our sortConfig whenever the value changes. This last part is optional but you’ll see why this is important for my assignment later on.

Following that we have a setSortColumn function that updates the sortableColumn$ observable whenever we select a column to sort by (you’ll see this in the HTML snippet) and our sort function which is used to determine which order the table should be sorted in based on the selected column and previous sort order.

Moving on to our table.component.html file we can make use of our table$ observable and the setSortColumn function like so:

Here we can use the (click) event binding to call setSortColumn whenever a table heading is clicked. This will pass the column to sort on into the sortDirection$ observable and toggle between descending and ascending order. To generate the rows, we use *ngFor to loop through the data in the table$ observable and use the async pipe to subscribe to the table$ to ensure we get the latest data.

When all is said and done, you’ll have something that works like this:

I didn’t show this in the HTML above but in my assignment I’m using the sortConfig value in my table to switch between icons. Whenever the sortConfig.column matches the currently selected column to sort on I switch from the default icon to one of the ascending or descending icons. If you select a different column to sort on then it will revert the previously selected columns icon to the default.

An added benefit to sorting this way is that when you use observables you can connect live data and your table will be updated automagically!

Well… That’s It! I hope this helps someone out there! It took me quite a few hours to figure this stuff out and I’m very happy with the outcome. Please leave any comments if you got ‘em!

--

--

I'm a Frontend Dev living in Melbourne, Australia and studying Computer Science. I love anything to do with web tech and am constantly trying to learn more!