development

Dynamic lists using AngularJS and Angular Material

We use AngularJS on a lot of our web projects, and since early last year we’ve been using Angular Material, the AngularJS implementation of Google’s Material Design. One interesting challenge that we’ve faced has been working with Angular Material before it has fully implemented the design spec. Additionally, when we’re building monitoring tools we often find ourselves needing to display large amounts of (often unknown length) data in table format.

Over the years jQuery Datatables has been the de facto library for this type of work, but while it’s powerful, it’s also bulky and the design felt a bit awkward when everything else we were doing had a bent toward Material Design.  The Angular Material team has an MD Datatable in their backlog, but we decided we couldn’t wait much longer, so we realized we’d need to spin up something on our own. We didn’t really need column-sorting which makes this a lot easier, but we don’t always know how many columns there are, and we don’t know how the data needs to be displayed. This all turned out to be far easier than we expected, so I thought I’d share it here.

jn-list

What we needed to build

Our directive definition required almost no logic, other than a scoped variable that we use for dynamically calculating column widths. Note, we namespace most of our custom directives with “jn”.

Most of what we needed was able to be achieved in the directive’s template:

We used Angular Material’s virtual-repeat directive for performance, since our unknown-length lists are sometimes quite long and we don’t want to crowd the DOM with thousands of list elements. This is where we use the actual data that we inject into the directive:

<md-list-item md-virtual-repeat=item in data layout=row>

Inside that, we repeat through the column definitions that get passed into the directive as options:

<span ng-repeat=”(k,v) in options.columns” ng-bind=”{{v}}” ng-style=”{width: 100/columnCount + ‘%’}”>

What this allow us to do is select a specific key within each item, and then by using ng-bind Angular will evaluate the full expression that we pass in so we can add custom filters for each column. We also set the width of each column here based on the number of columns defined. If you wanted specific widths per column, you could define your columns as objects, and pass in an addition width key there.

We added a few simple styles (we use LESS) for our specific implementation. Most of this is specific to our design, except for the defined height on the virtual repeat container, which you’re required to declare.

To use the directive, our data and options are formatted like this in the calling parent’s controller:

and then load the directive like this:

<jn-list options=”listOptions” data=”data”></jn-list>

While I’m happy to write custom logic in JavaScript, I love how clean directives can be when you move some of that logic into the directive’s template. We’ve been able to reuse this directive several times, so hopefully you’ll find somewhere to plug it in. If you want to come help us build things like this, we’re hiring 🙂

Discussion

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s