We can dynamically add axes, series, and points to any chart after it has been initialized. In the following examples, we will first initialize a chart and then add points and series to it upon different actions.
Consider the following code for a chart representing energy consumption by leading continents in 2013:
(function() { $( '#energy_consumption' ).highcharts({ title: { text: 'Energy Consumption in 2013' }, xAxis: { type: 'category', title: { text: 'Continents' } }, yAxis: { title: { text: 'Million Metric Tons of Oil Equivalent' } }, series: [{ name: 'Energy Consumption', type: 'column', data: [{ id: 'north-america', name: 'North America', y: 2786.7 }, { id: 'asia', name: 'Asia', y: 5594 }] }] }); })();
This chart will have two data points for two continents showing their energy consumption bar, that is, North America and Asia, respectively:
We will now add a button so that when someone clicks on it a new data point for Europe will be added to the series.
Add the following code for the button element:
<button data-action="add_europe">Add Europe Data Point</button>
Here, we are using HTML5 custom data attributes to define the behavior of the button.
The following is the JavaScript code to add a data point. Add it after the chart's initialization code:
var chart = $( '#energy_consumption' ).highcharts(), addEuropeBtn = $( '[data-action="add_europe"]' ); addEuropeBtn.on( 'click', function( e ) { if ( ! chart.get( 'europe' ) ) { chart.series[0].addPoint({ id: 'europe', name: 'Europe', y: 1286.1 }); } });
We first saved a reference to the initialized chart in the chart
variable and also cached a reference to the button in the addEuropeBtn
variable. Then, using the jQuery .on()
method, we added an anonymous function to be executed upon a click event of the button.
Inside the function, we added a condition to check whether the Europe data point has already been added to the series by the chart.get()
method. If the data point has not been added yet, it will return as null
. The condition will pass since the negation of null
is true
and a point will be added to the first series, that is, series[0]
, using the series.addPoint()
method.
Inside the series.addPoint()
method, we have passed an object literal containing the id
, name
, and y
value of the data point.
By clicking on the button, a new point will be added and the chart will be redrawn:
When adding multiple points at once, it's recommended to set the redraw argument of the addPoint()
method to false
and call the chart.redraw()
method explicitly after the point addition, as shown in the following generic code:
Button.on( 'click', function( e ) { chart.series[i].addPoint({...}, false); chart.series[i].addPoint({...}, false); chart.series[i].addPoint({...}, false); chart.redraw(); });
You can find more about the chart.addPoint()
method by visiting the following link on Highcharts documentation:
http://api.highcharts.com/highcharts#Series.addPoint
In the next section, we will look at adding a series dynamically to a chart.
Similar to a point, a series can also be added to a chart after it has been initialized. This is achieved by utilizing the chart.addSeries()
method that accepts a series object as its first argument.
Continuing with the previous example, we will now add a button to add a new series of type, pie
. The HTML code for the button is as follows:
<button data-action="add_pie">Add Pie Series</button>
Clicking on this button will create a new array of arrays, each containing a pair of series name
and its y
value. This array will be used as data for the newly added series:
var addPieSeriesBtn = $( '[data-action="add_pie"]' ), pieSeriesData = []; addPieSeriesBtn.on( 'click', function( e ) { if ( ! chart.get( 'percentage' ) ) { for ( var i in chart.series[0].data ) { pieSeriesData.push( [chart.series[0].data[i].name, chart.series[0].data[i].y] ); } var pieSeries = { name: 'Percentage', id: 'percentage', type: 'pie', data: pieSeriesData, center: ['80%', '25%'], size: 200, tooltip: { enabled: false }, dataLabels: { color: '#fff', distance: -45, y: -10, useHTML: true, formatter: function() { return this.point.name + '<br />' + this.percentage.toFixed( 2 ) + '%'; } } }; chart.setSize( 800, 450 ); chart.addSeries( pieSeries ); } });
We first gathered the data to be plotted from the series of the initialized chart in the form of an array containing the name
and y
value of the data points. These arrays will be collected in another array called pieSeriesData
.
In the next step, we initialized an object literal containing the properties of the new series. For its data
property, we passed the pieSeriesData
array. We used the formatter()
method to format the output of data labels. This will return the percentages representing each data point with two decimal places. To set the decimal places, we used the native JavaScript method, .toFixed()
, that accepts a number representing decimal places.
Finally, we increased the width of the chart using the chart.setSize()
method that accepts width
and height
as its arguments. This will make place for the newly added pie series. The series is added to the chart through the chart.addSeries()
method that accepts an object literal containing the properties of the series; in our case, it's pieSeries
.
This will produce the following result, given that the Europe data point is already added to the chart:
You can find more about the chart.addSeries()
method at the following link:
Now that we have plotted a chart that shows energy consumption data for three continents, we can add drilldown series to these data points showing a share of each country in the respective continent.
For the sake of simplicity, we will remove the pie series for now and pass the Europe data point as a chart configuration object:
$( '#energy_consumption' ).highcharts({ title: { ... }, xAxis: { ... }, yAxis: { ... }, series: [{ ... data: [{ name: 'North America', ... }, { name: 'Asia', ... }, { name: 'Europe', ... }] }] });
Adding drilldown to a point is as simple as adding a series, which we looked at in the previous section. It's accomplished via the chart.addSeriesAsDrilldown()
method that accepts the point
object to which the series is being added as its first argument. For the second argument, it accepts the series
object as the drilldown series.
For simulation purposes, we will create an object containing object literals for all the drilldown series in a key value pair. The key will be the ID of the data point and the value will be an object literal containing the drilldown series. The following code illustrates this:
var drilldownSeries = { 'north-america': { type: 'column', name: 'North America', data: [ ['U.S', 2265.8], ['Mexico', 188], ['Canada', 332.9] ] }, 'asia': { type: 'column', name: 'Asia', data: [ ['China', 2852.4], ['Russian Federation', 699], ['India', 595], ['Japan', 474], ['South Korea', 271.3], ['Iran', 243.9], ['Saudi Arabia', 227.7], ['Indonesia', 168.7], ['Kazakhstan', 62] ] }, 'europe': { type: 'column', name: 'Europe', data: [ ['Germany', 311.7], ['France', 248.4], ['UK', 200], ['Italy', 158.8], ['Spain', 133.7], ['Ukraine', 117.5], ['Australia', 116] ] } };
We also need to set the drilldown
property to true
on all the data points in the Energy Consumption
series:
series: [{ name: 'Energy Consumption', type: 'column', data: [{ ... name: 'North America', drilldown: true }, { ... name: 'Asia', drilldown: true }, { ... name: 'Europe', drilldown: true }] }]
We will now set up a functionality so that, when anyone clicks on a data point, a drilldown series will be added dynamically. In a real world scenario, the page will request the drilldown data from a server asynchronously, but here we are simulating that case by predefining the drilldown data in the form of a drilldownSeries
object.
Modify the chart
component in the chart configuration object to include a callback function for the drilldown
event:
chart: { events: { drilldown: function( e ) { this.addSeriesAsDrilldown( e.point, drilldownSeries[e.point.id] ); } } },
The callback function accepts the event object as its argument; it contains vital data about the event. When inspected with developer tools, it looks like the following:
Within this event object, an object for the point that has been clicked, that is, e.point
can be used as a point object when using the chart.addSeriesAsDrilldown()
method.
To pick up the right series from the drilldownSeries
object, we used e.point.id
as an identifier that will match the key of the correct object.
A chart can also be drilled up to the parent series programmatically using the chart.drillUp()
method.
Modify the drilldown
event in the chart
component as shown in the following code:
chart: { events: { drilldown: function( e ) { var chart = this; chart.addSeriesAsDrilldown( e.point, drilldownSeries[e.point.id] ); setTimeout(function() { chart.drillUp(); }, 5000 ); } } },
The chart will drill up to the parent series five seconds after the drilldown.
In the next section, we will look at various ways to set and get properties on a chart.