Sorting complex tables with AngularJS and Bootstrap
In this short article I will attempt to present an approach for enabling a table-like sorting mechanism for custom tables. Custom tables (as I see them) are tables that have extra UX behaviour, such as collapsible areas for showing and hiding additional data.
ngGrid is a wonderful directive which enables sorting behaviour for regular tables. There are several additional tools out there, but none of them support custom (or complex) tables (or bootstrap grid-system based tables).
The approach I am offering is flexible and uses the AngularJS bidirectional binding behaviour and ngRepeat.
Before I explain how it works, note that in my example I use Bootstrap for achieving the table formation, I am not using any <table> tags at all. If you don’t use Bootstrap in your project you’ll have to arrange your table formation manually with CSS. Additionally I am using underscore for the sorting logic and Font Awesome for the icons.
So here it goes:
Normally when you want to create a table-like component which shows any type of item data you would use ngRepeat and you pass it an array or collection of objects. When the array is being changed by the user, the ngRepeat directive watches the changes and reflects them to the DOM.
In my example you’ll find a directive which uses this behaviour and expects to receive two objects:
1. The same array that was sent to the ngRepeat.
2. A configuration object which holds data regarding the headers and data types of the columns.
The basic approach is to sort the array of objects given to the ngRepeat in the directive itself, according to the column being clicked. The bidirectional behaviour of the isolated scope in the directive affects the array and the ngRepeat that listen to it’s changes re-rendering the DOM elements.
You probably ask yourselves by now, why not using the orderBy filter ?
Well, it just not flexible enough. When you want to attach the sorting behaviour to the headers, enable reverse sorting and reuse it all over your app, it becomes quite challenging.
What else can you do:
You can call methods that exist in the directive from the controller, by using: $scope.sortColumnsMediator.sharedLogic[the method],
there are two methods available in the directive:
- scope.sortColumnsMediator.sharedLogic.isEnableSorting(true/false) - To enable or disable the sorting behaviour.
- scope.sortColumnsMediator.sharedLogic.sort() To manually (programmatically) sort the according the last sort.
Comments are available in the example.
Hope this helps,