Making ng2-charts work for us

Julián Fernández
BeeReal
Published in
5 min readAug 9, 2018

At our current project, we try to avoid installing new packages for our app. We prefer getting our hands dirty and building the things we need, exactly as we need them, from scratch. Sometimes, however, the project’s requirements and deadlines necessitate we forgo that, swallow our pride, and install a package.

This recently came up when we needed to display data in the form of charts — developing responsive, cross-browser-compatible charts from the ground up would have taken too long, so we decided to go with ng2-charts, an Angular 2 wrapper for the very popular Chart.js.

Installation of ng2-charts was a breeze with Angular CLI and getting it set up wasn’t difficult — however, as is often the case, the package didn’t do everything we needed exactly as we needed, so we got to work.

This is our basic chart, with several inputs and two outputs for click and hover events. Simple, right? The options work as you’d expect:

There’s a bit of fanciness here, such as the conditional expression in for each scales. This is something that we’ll need to overcome our first obstacle: implementing a button to switch between a regular bar chart and a stacked bar chart.

It should be simple but we discovered the chart broke and threw out errors when we simply changed that variable, so we had to come up with a solution. Changing the variable from true to false or vice versa is simple — getting the chart to behave wasn’t. We discovered the chart needed to be destroyed and re-rendered, so we made the following function, which destroys the chart, refills all the necessary information, and reinitializes it.

Destroying and re-rendering an object isn’t always the best choice, and performance-wise can be a big hit, but having the data saved to variables instead of requesting the API a second time shaves that time down to miliseconds.

That ‘cloned’ variable you see is simply a copy of the datasets we’re fetching from the backend.

And that does it for our stacked view! You can see the toggle button on the upper left.

After this came the really hard part: we were tasked with implement a feature wherein the user could click on a specific segment of the chart — not a bar but a segment of a bar, this is important — and would see a breakdown of the data in that segment in the form of a pie chart.

We quickly discovered that ng2-charts doesn’t provide out of the box support for this. Let’s investigate!

This is the click event for the chart. As you can see, it’s made up of two parts: the regular browser click event, with click coordinates, and ‘active’, which in this case has two items in it because the chart has two different objects being rendered (if you scroll up, you’ll see they’re called “Hotel (Lodging Only)” and “Personal Meals: Dinner”. Each of these objects has a huge amount of values and none of them have the information we need, which is what did the user click?.

The solution amounts to putting this inside the click event:

The variable chartElement prints as this:

which you’ll recognize as one of the two objects being shown by the full click event. Specifically, it’s what the user clicked on. Now this is data we can work with!

‘getElementAtEvent’ is a function that comes bundled with the wrapper but isn’t documented anywhere, which is the reason that a. it took a long time to find this solution and b. we consistently and obsessively document our custom functions, pipes and components at BeeReal.

Our backend expects the request for the data “breakdown” (what we’ll show in the pie chart) to have three values:

  1. a “summation” type (monthly, yearly, etc), determined via a Reactive form that’s outside the scope of this article.
  2. the category id of the corresponding chart segment (such as Hotel or Personal Meals, in our example)
  3. the date from which to calculate the data

Since 1. is already covered by another part of the app, we’ll recursively search the chartElement object for 2 and 3 and build a json called categoryBreakdownData with them.

It’s self-explanatory but just in case, the ‘selectedCategories’ variable is just an array with the categories being rendered in the original chart. In Chart.js parlance, a ‘tick’ is a discrete segment of an axis, such as each year in a chart showing data by year.

Rendering the pie chart is just as simple as rendering the bar chart. Note the conditional statement — this isn’t just good UI practice but also avoids overloading the console with error messages when the wrapper tries to render a table it has no data for.

There are some added complexities I’m not discussing here — such as using sass-loader to load Sass variables to use non-default, non-hardcoded colors for each element of the chart — but this should serve as a good primer of the kind of outside-the-box thinking we’ve grown used to applying here at BeeReal. We love building components from scratch but there’s also a certain joy in the challenge of getting something done quickly and creatively.

--

--