Custom Chart Tutorial Part Three

Welcome to part three of the custom chart tutorial. In this part, we explore how to integrate 3rd party libraries in custom charts, how to create a chart container, and how to use a library’s API to render a standard chart.

Identify Libraries

Zoomdata makes use of 3rd party libraries in the out of the box charts provided with the product. Typically, these libraries fall under two categories: charting libraries and utility libraries. The charting libraries assist with the rendering of standard chart types like bar, line, pie, and scatter plot charts. The utility libraries assist with shaping datasets, formatting values, or providing useful JavaScript methods.

In custom charts, you can also add libraries to assist with rendering and formatting requirements. Zoomdata requires 3rd party libraries to expose a “global” variable definition. Most popular JavaScript libraries provide a UMD (Universal Module Definition) that includes a global variable like the one required by Zoomdata.

Since we are creating a chart from scratch, let’s pick a charting library like Highcharts to assist with the rendering of this custom chart.

Add Libraries

The first step is to get a copy of Highcharts and save it your local file system. You can find the latest copy of highcharts.js here.

After you download the JavaScript file, you can use the CLI to associate the library with a chart. To begin, let’s add the highcharts.js library to the Zoomdata server:

zd-chart add --type library "highcharts.js" <path-to-highcharts.js>

Next, let’s link the library to the chart “My First Custom Chart”.

zd-chart edit "My First Custom Chart"

Answer the prompts with the following selections:

  1. Libraries
  2. Include/Exclude libraries in the chart:
  3. highcharts.js

Note: lodash.min.js is pre-selected as one of the included libraries in the chart. You can use the spacebar to make more than one selection.

Now, let’s verify that we can we can access the Highcharts global variable from the chart’s code.

Test Libraries

In a terminal window, change directories to the local directory of “My First Custom Chart” and enter zd-chart watch to set the CLI to Watch mode. For a refresher on this topic, visit the “Edit the Chart’s Code” section part one of this tutorial.

Open the Visualization.js file in your preferred text editor or IDE. Let’s add the following line towards the top of the file:

/* global controller */

console.log(
	Highcharts ? 'The library is defined.' : 'The library is undefined'
);

var groupAccessor = controller.dataAccessors['Group By'];
var metricAccessor = controller.dataAccessors.Size;
//...

Now check the contents of the browser console when adding the chart to a dashboard. The following image shows what the console should look like:

The library is defined

Once you confirm that the global variable is defined, you can remove the console.log statement.

Create a Chart Container

As part of its charting API, Zoomdata provides a <div> element that can hold the rendered contents of your custom chart. While it is perfectly fine to use that element as the chart container, it is recommended to create a separate container inside of that element to gain full control over its styles.

Add the following lines of code to the top of the Visualization.js file:

/* global controller */

// create chart container
var chartContainer = document.createElement('div');
chartContainer.style.width = '100%';
chartContainer.style.height = '100%';
chartContainer.classList.add('chart-container');
controller.element.appendChild(chartContainer);

var groupAccessor = controller.dataAccessors['Group By'];
var metricAccessor = controller.dataAccessors.Size;
//...

Notice the line: controller.element.appendChild(chartContainer);. controller.element is the <div> Zoomdata provides with its API.

Let’s try modifying the background color of the newly added container. Open the style.css component file, clear its contents, and add the following lines to the top of the file:

.chart-container {
  background-color: #323232;
}

Refresh the dashboard with the custom chart, and you should see a dark gray background. The image below shows what your chart should look like:

Chart with dark gray background

If you were able to see the dark gray background, the chart container is working. Change the background color to background-color: #ffffff; to set it back to white.

Render the Chart

In part two of this tutorial, we defined a group-by variable and a metric variable to generate a grouped dataset with a single metric value. This data structure works well with bar and pie charts. Let’s use the Highcharts API to create a pie chart with our dataset.

In the Visualization.js file, let’s instantiate a variable to hold an instance of the pie chart. The chart’s instance is created by using the Highcharts.chart class member and passing a chart container and the chart options. Let’s add it right below our data accessors:

//...
var groupAccessor = controller.dataAccessors['Group By'];
var metricAccessor = controller.dataAccessors.Size;

var chart = Highcharts.chart(chartContainer, {
	chart: {
		type: 'pie',
	},
	title: {
		text: ''
	},
	plotOptions: {
		pie: {
			allowPointSelect: true,
			cursor: 'pointer',
		},
	},
	series: [
		{
			name: metricAccessor.getLabel(),
		},
	],
});
//...

Notice how we used the metric accessor to dynamically capture the name of the series.

Next, let’s make a slight change to our reshapeData function. Highcharts expects a “y” property in the objects of the data array. The following code will the change the property name from “value” to “y”:

//...
function reshapeData(data) {
  return data.map(function(d) {
    return {
      name: groupAccessor.raw(d),
      y: metricAccessor.raw(d),
    };
  });
}

Finally, let’s call the chart’s update method inside of the controller.update function to pass it the chart’s data:

//...
controller.update = function(data) {
  // Called when new data arrives
  chart.update({
    series: [
      {
        name: metricAccessor.getLabel(),
        data: reshapeData(data),
      },
    ],
  });
};
//...

We have pie chart rendering! Your chart should look similar to this: Pie Chart not Resized

Hmm, there is a problem. The pie chart is cut-off at the bottom. If we resize the window, the chart does not resize accordingly.

Handle Resizing

Zoomdata provides an API to notify the charts of a resize operation. Let’s add controller.resize function at the end of the Visualization.js file to handle resizing.

//...
controller.resize = function(newWidth, newHeight) {
  // Called when the widget is resized
  chart.reflow();
};

Here we are calling the reflow method of the Highchart’s chart instance to tell the chart to fit the new dimensions of the chart container.

Now that we are handling chart resizing, our chart should look like the following image: Pie Char Resized

Feel free to play around and add some filters, or change the chart’s default configuration. You should see the data re-render as modify the query with the filter or timebar control.

Looking Good!

We now have chart that we can re-use with any data source. Head over to Part Four to learn about adding and removing chart controls and integrating with Zoomdata tooltips and the radial menu.