I have a DataTable that looks something like this:
+-------+---------+--------+
| month | name | income |
+-------+---------+--------+
| Jan | Alice | $5,000 |
| Feb | Alice | $3,000 |
| Mar | Alice | $4,500 |
| Jan | Bob | $2,750 |
| Feb | Bob | $8,000 |
| Mar | Bob | $1,000 |
| Jan | Charlie | $3,500 |
| Feb | Charlie | $4,100 |
| Mar | Charlie | $3,900 |
... ... ...
I wish to display a Google Visualization with one ChartWrapper and one ControlWrapper.
The ChartWrapper will display a Table, but I only want this Table to show the most recent month. To do this I'm using .setView()
on the ChartWrapper.
The ControlWrapper will wrap a CategoryFilter on the name column.
The issue I'm running into is that when I try to select a name, it throws an error: Invalid row index ... Should be in range [0-...]
I believe I'm getting this issue because setView
accepts a static array of rows to display, but if the table is filtered then the rows to display will be different. I'm calling setView
like so:
var recentRows = dataTable.getFilteredRows([
{
"column": 2,
"minValue": dataTable.getColumnRange(2).max
}
]);
chartWrapper.setView({
"rows": recentRows
});
when using the Dashboard
control,
the ChartWrapper
and ControlWrapper
need to be in sync and use the same data set
as you've found, setting the view
property only on the chart throws this off
to correct, use a DataView
to draw the dashboard,
as seen in the following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['controls']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['month', 'name', 'income'],
[0, 'Alice', 5000],
[1, 'Alice', 3000],
[2, 'Alice', 4500],
[0, 'Bob', 2750],
[1, 'Bob', 8000],
[2, 'Bob', 1000],
[0, 'Charlie', 3500],
[1, 'Charlie', 4100],
[2, 'Charlie', 3900]
]);
var control = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'control',
options: {
filterColumnLabel: 'name',
ui: {
allowTyping: false,
allowMultiple: true
}
}
});
var chart = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'chart'
});
var view = new google.visualization.DataView(data);
view.setRows(data.getFilteredRows([{
column: 0,
minValue: data.getColumnRange(0).max
}]));
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard')
);
dashboard.bind(control, chart);
dashboard.draw(view);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="control"></div>
<div id="chart"></div>
another option would be not to use a dashboard
draw each wrapper independently,
then listen for the statechange
event on the control,
and draw the table accordingly
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['controls']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['month', 'name', 'income'],
[0, 'Alice', 5000],
[1, 'Alice', 3000],
[2, 'Alice', 4500],
[0, 'Bob', 2750],
[1, 'Bob', 8000],
[2, 'Bob', 1000],
[0, 'Charlie', 3500],
[1, 'Charlie', 4100],
[2, 'Charlie', 3900]
]);
var control = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'control',
dataTable: data,
options: {
filterColumnLabel: 'name',
ui: {
allowTyping: false,
allowMultiple: true
}
}
});
control.draw();
var chart = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'chart',
dataTable: data
});
google.visualization.events.addListener(control, 'ready', drawTable);
google.visualization.events.addListener(control, 'statechange', drawTable);
drawTable();
function drawTable() {
var filters = [{
column: 0,
minValue: data.getColumnRange(0).max
}];
var selectedNames = control.getState().selectedValues;
if (selectedNames.length > 0) {
filters.push({
column: 1,
test: function (value, row, column, table) {
return (selectedNames.indexOf(table.getValue(row, column)) > -1);
}
});
}
chart.setView({
rows: data.getFilteredRows(filters)
});
chart.draw();
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="control"></div>
<div id="chart"></div>