Reputation: 796
I have created a dual axis combo chart using the Google Visualization API that displays data as column and line charts.
the page also has a set of filters for the columns which returns a new data set from the database depending on the column filters selected.
In order to assign which values are bars and lines I have used the series option which is shown in the jsfiddle and code below:
google.charts.load('current',
{
callback: drawChart,
packages: ['corechart', 'controls', 'charteditor']
});
var chart;
function drawChart() {
var data = new google.visualization.arrayToDataTable([['Outcomes','Abstinent','Improved','Unchanged','Deteriorated','Average no. of days use at start','Average no. of days of use at review'],['2015/16',18036,11414,14430,1880,21.6,8.3],['2016/17',17642,11688,14010,1738,22.2,8.5],['2017/18',17282,10796,13542,1686,22.1,8.6]]);
var width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0) + 'px';
var columnsTable = new google.visualization.DataTable();
columnsTable.addColumn('number', 'colIndex');
columnsTable.addColumn('string', 'colLabel');
var initState = { selectedValues: [] };
// put the columns into this data table (skip column 0)
for (var i = 1; i < data.getNumberOfColumns(); i++) {
columnsTable.addRow([i, data.getColumnLabel(i)]);
// you can comment out this next line if you want to have a default selection other than the whole list
initState.selectedValues.push(data.getColumnLabel(i));
}
// you can set individual columns to be the default columns (instead of populating via the loop above) like this:
// initState.selectedValues.push(data.getColumnLabel(4));
var options = {
title: 'Treatment outcomes',
hAxis: {
slantedText: true,
slantedTextAngle: 30,
title: 'Reporting Period'
},
vAxes: {
0: { logScale: false, title: 'No. of clients' },
1: { logScale: false, title: 'Average no. of days use', maxValue: 28 }
},
series: {
0: { type: "bars", targetAxisIndex: 0, color: '#FF9900' },
1: { type: "bars", targetAxisIndex: 0, color: '#FF6400' },
2: { type: "bars", targetAxisIndex: 0, color: '#FF0000' },
3: { type: "bars", targetAxisIndex: 0, color: '#9A0033' },
4: { type: "line", targetAxisIndex: 1 },
5: { type: "line", targetAxisIndex: 1 }
},
chartArea: {
top: 40,
left: 100,
width: "65%"
},
pointSize: 5,
legend: { position: 'top' },
width: width,
height: '300px'
}
var chart = new google.visualization.LineChart(document.getElementById("chart_div"));
chart.draw(data, options);
}
https://jsfiddle.net/uLwtbvn5/5/
I am looking to have it so that if a value or values are removed any value with the column name Abstinent, Improved, Unchanged or Deteriorated is always shown as a bar and uses targetAxisIndex: 0 and the values with Average no. of days use at start or Average no. of days of use at review are always lines and use targetAxisIndex: 1.
Is there are way of doing this with the Google Visualization API?
Upvotes: 1
Views: 319
Reputation: 61222
on the columnsTable
, use row properties to store the series options.
then when the filter changes, pull the row properties from the columns table to draw the chart.
see following working snippet...
google.charts.load('current', {
packages: ['corechart', 'controls', 'charteditor']
}).then(function () {
var data = google.visualization.arrayToDataTable([['Outcomes','Abstinent','Improved','Unchanged','Deteriorated','Average no. of days use at start','Average no. of days of use at review'],['2015/16',18036,11414,14430,1880,21.6,8.3],['2016/17',17642,11688,14010,1738,22.2,8.5],['2017/18',17282,10796,13542,1686,22.1,8.6]]);
var width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0) + 'px';
// define bars series colors
var colors = ['#ff9900', '#ff6400', '#ff0000', '#9a0033'];
// define filter columns
var columnsTable = new google.visualization.DataTable();
columnsTable.addColumn('number', 'Series #');
columnsTable.addColumn('string', 'Select series: ');
var initState = { selectedValues: [] };
for (var i = 1; i < data.getNumberOfColumns(); i++) {
var colIndex = columnsTable.addRow([i, data.getColumnLabel(i)]);
initState.selectedValues.push(data.getColumnLabel(i));
// assign series type, axis, and color -- store using row properties
switch (data.getColumnLabel(i)) {
case 'Abstinent':
case 'Improved':
case 'Deteriorated':
case 'Unchanged':
columnsTable.setRowProperty(colIndex, 'type', 'bars');
columnsTable.setRowProperty(colIndex, 'targetAxisIndex', 0);
columnsTable.setRowProperty(colIndex, 'color', colors[colIndex]);
break;
default:
columnsTable.setRowProperty(colIndex, 'type', 'line');
columnsTable.setRowProperty(colIndex, 'targetAxisIndex', 1);
}
}
// define chart
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
// define filter
var filter = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'filter_div',
dataTable: columnsTable,
options: {
filterColumnIndex: 1,
ui: {
caption: 'Series',
sortValues: false
}
},
state: initState
});
// draw chart when filter is ready or changed
google.visualization.events.addListener(filter, 'ready', drawChart);
google.visualization.events.addListener(filter, 'statechange', drawChart);
// draw filter
filter.draw();
// draw chart
function drawChart() {
var options = {
title: 'Treatment outcomes',
hAxis: {
slantedText: true,
slantedTextAngle: 30,
title: 'Reporting Period'
},
vAxes: {
0: { logScale: false, title: 'No. of clients' },
1: { logScale: false, title: 'Average no. of days use', maxValue: 28 }
},
series: {},
chartArea: {
top: 40,
left: 100,
width: '65%'
},
pointSize: 5,
legend: { position: 'top' },
width: width,
height: '300px'
};
// define data view column and series options based on filter columns
var viewColumns = [0];
var state = filter.getState().selectedValues;
state.forEach(function (column, index) {
var colIndex;
// find filter column index
for (var i = 0; i < columnsTable.getNumberOfRows(); i++) {
if (columnsTable.getValue(i, 1) === column) {
colIndex = i;
}
}
viewColumns.push(colIndex + 1);
// define series option
options.series[index] = {
type: columnsTable.getRowProperty(colIndex, 'type'),
targetAxisIndex: columnsTable.getRowProperty(colIndex, 'targetAxisIndex')
};
if (colIndex < 4) {
options.series[index].color = columnsTable.getRowProperty(colIndex, 'color');
}
});
// define data view
var dataView = new google.visualization.DataView(data);
dataView.setColumns(viewColumns);
// ensure enough columns selected to draw chart
if (viewColumns.length > 1) {
chart.draw(dataView, options);
} else {
chart.clearChart();
}
}
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="filter_div"></div>
<div id="chart_div"></div>
Upvotes: 1