Working on my AngularJS app that visualizes historical playback of received Amateur Radio signals (www.spotviz.info) I wanted to have a ‘heatmap’ type display that shows density of the received signals per day (or hour). Searching around, the most common library to display a heatmap seems to be Cal-HeatMap. And since this is an AngularJS based app, it makes sense to use a directive to display the heatmap in my view where needed – Angular Cal-HeatMap seemed to be what I needed.
Starting with anything new it’s far easier to build something small that works first, and then include it into something larger/more complicated. Here’s my standalone test app using Angular Cal-HeatMap with Cal-HeatMap. It has hardcoded data, just to show the heatmap rendering.
The first issue I ran into, was that my standalone app was rendering fine, but copying the same directive usage into my SpotViz app, I could not get the directive to recognize my config options, or render any data.
As with everything I’ve found so far with AngularJS, sometimes stuff that should be easy turns out to be hard, but in most cases only because I don’t understand what’s going on, or how I assume it to be working is completely wrong At least I’m not the only one who finds this about AngularJS, to quote Nathan LeClair from one of his posts:
"As I’ve gotten a little into AngularJS I’ve been surprised by how often my assumptions about how things will work have turned out to be wrong".
I don’t know if this is an issue specifically with how Angular Cal-HeatMap directive is implemented or not, but the way I was trying to use it, it appears it initializes before the point where I retrieve and setup the data for display. Once I retrieve the data, setting it in the $scope variable that the directive is using seems to have no effect; it doesn’t see the data and display as I’d expect.
My work around for this was to use ng-if to only initialize the directive when I toggle a flag after the data is ready. Previously I was using ng-show to toggle the display of the directive, but that apparently causes the directive to initialize even though it’s not visible. I don’t know if there’s something else I can do to re-initialize the directive, but this works for now.
Here’s what I ended up with:
<cal-heatmap ng-if="search.showDataDensity" config="search.heatmap.config"></cal-heatmap>
For context, here’s an example of what the heatmap looks like with some example received signal data from 2014:
Cal-HeatMap uses 5 CSS styles by default for coloring according to how many data points are for each date, from .q1 through .q5. For data with a count > that whatever the top range is set to, apparently css class .q6 gets applied. Without any other change however, if you haven’t defined your own .q6, these dates will be displayed as if there’s no data on those dates. This wasn’t obvious to me, but is discussed in this post on SO. Add a custom CSS class for .q6 with a slightly darker color than .q5, problem solved.
I’ve some polishing and cleanup to do, but my heatmap display is almost ready to go!
(Page views: 5)