Hi,
I have given my sample data. My steps
- Create one dashboard with two charts and two Category Filters
- For each chart use a different filtered DataView
- this data comes from SQL query where first column gives what kind of chart it is
- Use a dummy table and event listeners to apply different filtered views to each chart
I am facing following problems (my Chrome version = 103.0.5060.134 (Official Build) (64-bit))
- On load the browser shows the error "Cannot read properties of null (reading '$')" - screen shot attached
- The category filters are working but when I click on bar, the whole chart freezes
- in Chrome debug console I see error
jsapi_compiled_default_module.js:493 Uncaught TypeError: f.getTableRowIndex is not a function
at gvjs_ho.<anonymous> (jsapi_compiled_default_module.js:493:195)
at Array.map (<anonymous>)
at gvjs_v (jsapi_compiled_default_module.js:63:315)
at gvjs_.Hqa (jsapi_compiled_default_module.js:493:117)
at gvjs_H.<anonymous> (jsapi_compiled_default_module.js:166:147)
at gvjs_ni (jsapi_compiled_default_module.js:165:214)
at gvjs_.dispatchEvent (jsapi_compiled_default_module.js:163:405)
at gvjs_I (jsapi_compiled_default_module.js:165:635)
at jsapi_compiled_default_module.js:465:272
at gvjs_H.<anonymous> (jsapi_compiled_default_module.js:166:147)
At the top of debug console I see
loader.js:148 Attempting to load version '51' of Google Charts, but the previously loaded 'current' will be used instead.
Can you please help me out here to resolve the above issues?
My requirement is different charts with filtered data from same datas ource but each charts should have its own DataView.
Thank you
with warm regards
ramki
<html>
<head>
<!--Load the AJAX API CHROME VERSION Version 103.0.5060.134 (Official Build) (64-bit)-->
<script type="text/javascript" src="
https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Load the Visualization API and the controls package.
google.charts.load('current', {'packages':['corechart', 'controls']});
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawDashboard);
// Callback that creates and populates a data table,
// instantiates a dashboard, a range slider and a pie chart,
// passes in the data and draws it.
function drawDashboard() {
var sampleData = [[{label:'Chart Index', id:'chartindex', type: 'string'}, {label:'Product', id:'jirapkey', type: 'string'}, {label:'Customer', id:'customer', type: 'string'}, {label:'Text Col1', id:'txtcol1', type: 'string'}, {label:'Num1', id:'n1', type: 'number'}, {label:'Num2', id:'n2', type: 'number'}, {label:'Num3', id:'n3', type: 'number'}], ['createdresolved_by_origin_chart9', 'All', 'All', 'Customer', 4475, 4058, 0], ['createdresolved_by_origin_chart9', 'All', 'All', 'OPS', 3211, 3015, 0], ['createdresolved_by_origin_chart9', 'All', 'All', 'R&D', 16824, 15597, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer B', 'Customer', 404, 378, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer B', 'OPS', 704, 677, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer B', 'R&D', 130, 107, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer C', 'Customer', 240, 228, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer C', 'OPS', 107, 102, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer C', 'R&D', 221, 204, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer A', 'Customer', 631, 560, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer A', 'OPS', 393, 353, 0], ['createdresolved_by_origin_chart9', 'All', 'Customer A', 'R&D', 975, 896, 0], ['createdresolved_by_origin_chart9', 'Product A', 'All', 'Customer', 902, 774, 0], ['createdresolved_by_origin_chart9', 'Product A', 'All', 'OPS', 728, 663, 0], ['createdresolved_by_origin_chart9', 'Product A', 'All', 'R&D', 5721, 5096, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer B', 'Customer', 37, 32, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer B', 'OPS', 106, 97, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer B', 'R&D', 47, 32, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer C', 'Customer', 23, 21, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer C', 'OPS', 16, 16, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer C', 'R&D', 12, 8, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer A', 'Customer', 78, 73, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer A', 'OPS', 64, 61, 0], ['createdresolved_by_origin_chart9', 'Product A', 'Customer A', 'R&D', 44, 36, 0], ['createdresolved_by_origin_chart9', 'Product B', 'All', 'Customer', 1351, 1189, 0], ['createdresolved_by_origin_chart9', 'Product B', 'All', 'OPS', 751, 685, 0], ['createdresolved_by_origin_chart9', 'Product B', 'All', 'R&D', 2742, 2423, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer B', 'Customer', 93, 86, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer B', 'OPS', 173, 164, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer B', 'R&D', 23, 19, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer C', 'Customer', 70, 64, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer C', 'OPS', 29, 26, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer C', 'R&D', 22, 19, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer A', 'Customer', 256, 222, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer A', 'OPS', 54, 48, 0], ['createdresolved_by_origin_chart9', 'Product B', 'Customer A', 'R&D', 580, 521, 0], ['createdresolved_by_origin_chart9', 'Product C', 'All', 'Customer', 1235, 1169, 0], ['createdresolved_by_origin_chart9', 'Product C', 'All', 'OPS', 944, 913, 0], ['createdresolved_by_origin_chart9', 'Product C', 'All', 'R&D', 7345, 7156, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer B', 'Customer', 86, 83, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer B', 'OPS', 82, 82, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer B', 'R&D', 35, 32, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer C', 'Customer', 133, 129, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer C', 'OPS', 49, 47, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer C', 'R&D', 151, 147, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer A', 'Customer', 155, 139, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer A', 'OPS', 165, 144, 0], ['createdresolved_by_origin_chart9', 'Product C', 'Customer A', 'R&D', 332, 321, 0], ['by_status_chart10', 'Product B', 'Customer C', 'Closed', 36, 0, 0], ['by_status_chart10', 'Product A', 'Customer B', 'Closed', 74, 0, 0], ['by_status_chart10', 'Product B', 'Customer B', 'Closed', 177, 0, 0], ['by_status_chart10', 'Product B', 'All', 'Closed', 2013, 0, 0], ['by_status_chart10', 'Product A', 'Customer C', 'Closed', 15, 0, 0], ['by_status_chart10', 'Product A', 'Customer A', 'Closed', 67, 0, 0], ['by_status_chart10', 'All', 'Customer C', 'Closed', 347, 0, 0], ['by_status_chart10', 'All', 'Customer A', 'Closed', 1092, 0, 0], ['by_status_chart10', 'Product C', 'Customer A', 'Closed', 551, 0, 0], ['by_status_chart10', 'Product C', 'Customer C', 'Closed', 281, 0, 0], ['by_status_chart10', 'Product C', 'Customer B', 'Closed', 182, 0, 0], ['by_status_chart10', 'Product C', 'All', 'Closed', 8582, 0, 0], ['by_status_chart10', 'All', 'All', 'Closed', 15315, 0, 0], ['by_status_chart10', 'All', 'Customer B', 'Closed', 589, 0, 0], ['by_status_chart10', 'Product A', 'All', 'Closed', 3715, 0, 0], ['by_status_chart10', 'Product B', 'Customer A', 'Closed', 403, 0, 0], ['by_status_chart10', 'All', 'All', 'Resolved', 7354, 0, 0], ['by_status_chart10', 'All', 'Customer B', 'Resolved', 573, 0, 0], ['by_status_chart10', 'All', 'Customer C', 'Resolved', 187, 0, 0], ['by_status_chart10', 'All', 'Customer A', 'Resolved', 717, 0, 0], ['by_status_chart10', 'Product A', 'All', 'Resolved', 2817, 0, 0], ['by_status_chart10', 'Product A', 'Customer B', 'Resolved', 87, 0, 0], ['by_status_chart10', 'Product A', 'Customer C', 'Resolved', 30, 0, 0], ['by_status_chart10', 'Product A', 'Customer A', 'Resolved', 103, 0, 0], ['by_status_chart10', 'Product B', 'All', 'Resolved', 2284, 0, 0], ['by_status_chart10', 'Product B', 'Customer B', 'Resolved', 92, 0, 0], ['by_status_chart10', 'Product B', 'Customer C', 'Resolved', 73, 0, 0], ['by_status_chart10', 'Product B', 'Customer A', 'Resolved', 388, 0, 0], ['by_status_chart10', 'Product C', 'All', 'Resolved', 656, 0, 0], ['by_status_chart10', 'Product C', 'Customer B', 'Resolved', 15, 0, 0], ['by_status_chart10', 'Product C', 'Customer C', 'Resolved', 42, 0, 0], ['by_status_chart10', 'Product C', 'Customer A', 'Resolved', 53, 0, 0], ['by_status_chart10', 'Product C', 'All', 'Open', 275, 0, 0], ['by_status_chart10', 'Product C', 'Customer B', 'Open', 6, 0, 0], ['by_status_chart10', 'Product C', 'Customer C', 'Open', 9, 0, 0], ['by_status_chart10', 'Product C', 'Customer A', 'Open', 45, 0, 0], ['by_status_chart10', 'All', 'Customer A', 'Open', 143, 0, 0], ['by_status_chart10', 'All', 'Customer C', 'Open', 21, 0, 0], ['by_status_chart10', 'Product A', 'Customer A', 'Open', 7, 0, 0], ['by_status_chart10', 'Product A', 'Customer C', 'Open', 2, 0, 0], ['by_status_chart10', 'Product B', 'All', 'Open', 367, 0, 0], ['by_status_chart10', 'All', 'All', 'Open', 1449, 0, 0], ['by_status_chart10', 'Product B', 'Customer B', 'Open', 15, 0, 0], ['by_status_chart10', 'Product A', 'Customer B', 'Open', 18, 0, 0], ['by_status_chart10', 'Product B', 'Customer C', 'Open', 5, 0, 0], ['by_status_chart10', 'Product A', 'All', 'Open', 632, 0, 0], ['by_status_chart10', 'Product B', 'Customer A', 'Open', 65, 0, 0], ['by_status_chart10', 'All', 'Customer B', 'Open', 60, 0, 0], ['by_status_chart10', 'Product A', 'All', 'Need Info', 187, 0, 0], ['by_status_chart10', 'Product B', 'Customer A', 'Need Info', 34, 0, 0], ['by_status_chart10', 'All', 'All', 'Need Info', 392, 0, 0], ['by_status_chart10', 'All', 'Customer B', 'Need Info', 16, 0, 0], ['by_status_chart10', 'Product B', 'All', 'Need Info', 180, 0, 0], ['by_status_chart10', 'Product A', 'Customer B', 'Need Info', 11, 0, 0], ['by_status_chart10', 'Product C', 'All', 'Need Info', 11, 0, 0], ['by_status_chart10', 'Product A', 'Customer A', 'Need Info', 9, 0, 0], ['by_status_chart10', 'Product C', 'Customer C', 'Need Info', 1, 0, 0], ['by_status_chart10', 'Product A', 'Customer C', 'Need Info', 4, 0, 0], ['by_status_chart10', 'Product C', 'Customer A', 'Need Info', 3, 0, 0], ['by_status_chart10', 'All', 'Customer A', 'Need Info', 47, 0, 0], ['by_status_chart10', 'Product B', 'Customer B', 'Need Info', 5, 0, 0], ['by_status_chart10', 'All', 'Customer C', 'Need Info', 13, 0, 0], ['by_status_chart10', 'Product B', 'Customer C', 'Need Info', 7, 0, 0]];
// Create our data table.
var data = google.visualization.arrayToDataTable(sampleData);
// Create a dashboard.
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div'));
var productSelect = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'product_filter_div',
'options': {
'filterColumnLabel': 'Product',
'ui' : {
'caption' : 'Choose Product',
'label' : 'Choose Product',
'labelStacking' : 'vertical',
'allowMultiple' : false,
'allowNone' : false,
'allowTyping' : false, //instead of input box, this make it as button
}
},
state: {'selectedValues': ['All']}
});
var customerSelect = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'customer_filter_div',
'options': {
'filterColumnLabel': 'Customer',
'ui' : {
'caption' : 'Choose Customer',
'label' : 'Choose Customer',
'labelStacking' : 'vertical',
'allowMultiple' : false,
'allowNone' : false,
'allowTyping' : false, //instead of input box, this make it as button
}
},
state: {'selectedValues': ['All']}
});
var dummy = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'DummyTable',
options: {
sort: 'disable' // disable sorting on the dummy table to reduce the number of event handlers spawned
},
view: {
rows: [] // remove all rows from the view so it doesn't waste time rendering them in HTML
}
});
// Create a column chart, passing some options
var createdResolved_byOrigin_ColumnChart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'createdResolved_byOrigin_chart_div',
options: {
'width': '90%',
'height': '80%',
'chartArea': {
width: '80%',
height: '60%',
},
legend: {'position': 'bottom', 'textStyle': {'color': 'blue', 'fontSize': 14}},
colors: ['#41a1d0', '#87b77e'],
}
});
// Create a pie chart, passing some options
var bugsCreated_byStatus_pieChart = new google.visualization.ChartWrapper({
chartType: 'PieChart',
containerId: 'bugsCreated_byStatus_chart_div',
options: {
'width': '95%',
'height': '95%',
'chartArea': {
width: '80%',
height: '75%',
},
pieSliceText: 'value',
legend: {'position':'bottom','alignment':'left'},
}
});
// Establish dependencies, declaring that 'filter' drives 'pieChart',
// so that the pie chart will only display entries that are let through
// given the chosen slider range.
dashboard.bind([productSelect, customerSelect], [dummy, createdResolved_byOrigin_ColumnChart, bugsCreated_byStatus_pieChart]);
// Draw the dashboard.
dashboard.draw(data);
google.visualization.events.addListener(productSelect, 'ready', reDrawChartsFunction);
google.visualization.events.addListener(productSelect, 'statechange', reDrawChartsFunction);
google.visualization.events.addListener(customerSelect, 'ready', reDrawChartsFunction);
google.visualization.events.addListener(customerSelect, 'statechange', reDrawChartsFunction);
function reDrawChartsFunction() {
var productSelected = productSelect.getState();
var customerSelected = customerSelect.getState();
var dataViewFor_createdResolved_byOrigin_ColumnChart = new google.visualization.DataView(dummy.getDataTable());
// this line from
https://developers.google.com/chart/interactive/docs/reference#DataTable_getFilteredRows dataViewFor_createdResolved_byOrigin_ColumnChart
.setRows(dataViewFor_createdResolved_byOrigin_ColumnChart
.getFilteredRows([{column: 0, value: 'createdresolved_by_origin_chart9'}
])
);
// group the data of the filtered table and set the result in the pie chart.
createdResolved_byOrigin_ColumnChart.setDataTable( google.visualization.data.group(
// get the filtered results
dataViewFor_createdResolved_byOrigin_ColumnChart,
[3],
[{'column': 4, 'aggregation': google.visualization.data.sum, 'type': 'number'}
,{'column': 5, 'aggregation': google.visualization.data.sum, 'type': 'number'}],
));
// setView is to decide which column indexes or rows considered for charting
// here dummyTable view is used so 0 is pkey, 1 is created_count and 2 is resolved_count
//
https://stackoverflow.com/questions/46219896/google-visualization-dashboard-with-filter-and-dataview createdResolved_byOrigin_ColumnChart.setView({'columns': [0, 1, 2]})
// redraw the pie chart to reflect changes
createdResolved_byOrigin_ColumnChart.draw();
var dataViewFor_bugsCreated_byStatus_pieChart = new google.visualization.DataView(dummy.getDataTable());
dataViewFor_bugsCreated_byStatus_pieChart
.setRows(dataViewFor_bugsCreated_byStatus_pieChart
.getFilteredRows([{column: 0, value: 'by_status_chart10'}
])
);
bugsCreated_byStatus_pieChart.setDataTable( google.visualization.data.group(
// get the filtered results
dataViewFor_bugsCreated_byStatus_pieChart,
[3],
[{'column': 4, 'aggregation': google.visualization.data.sum, 'type': 'number'}]
));
//index from filtered dummy table
bugsCreated_byStatus_pieChart.setView({'columns': [0, 1]})
// redraw the pie chart to reflect changes
bugsCreated_byStatus_pieChart.draw();
} //END function reDrawChartsFunction()
} //END function drawDashboard()
</script>
</head>
<body>
<!--Div that will hold the dashboard-->
<div id="dashboard1_div">
<div id="product_filter_div" style="width: 145px; height: 50px; display: inline-block;"></div>
<div id="customer_filter_div" style="width: 145px; height: 50px; display: inline-block;"></div>
<div id="DummyTable" style="display: none;" ></div>
<div id="createdResolved_byOrigin_chart_div" style="width: 600px; height: 400px;"></div>
<div id="bugsCreated_byStatus_chart_div" style="width: 450px; height: 350px;"></div>
</div>
</body>
</html>