Reputation: 95
Following this post: Embedding a line chart inside a google chart table inside an html page
I want to get a table that looks like this:
Only replacing the line chart with a dashboard chart like the following:
Run the following snippet with my code to see the results I'm getting.
google.charts.load('current', {
'packages': ['corechart', 'controls', 'table', 'charteditor']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var tableData = new google.visualization.DataTable();
tableData.addColumn('string', 'Name');
tableData.addColumn('number', 'Salary');
tableData.addColumn('string', 'Chart');
tableData.addColumn('string', 'Test');
tableData.addRows([
['Mike', {
v: 10000,
f: '$10,000'
}, null, '5thFirst'],
['Jim', {
v: 8000,
f: '$8,000'
}, null, '5thSecond'],
['Alice', {
v: 12500,
f: '$12,500'
}, null, '5thThird'],
['Bob', {
v: 7000,
f: '$7,000'
}, null, '5thForth']
]);
var table = new google.visualization.Table(document.getElementById('table_div'));
google.visualization.events.addListener(table, 'ready', function() {
// table body
Array.prototype.forEach.call(table.getContainer().getElementsByTagName('tbody'), function(tableBody) {
// table rows
Array.prototype.forEach.call(tableBody.rows, function(tableRow, rowIndex) {
// table cells
Array.prototype.forEach.call(tableRow.cells, function(tableCell, cellIndex) {
// determine if last cell
if (cellIndex === (2)) {
// var dashboardDiv = document.createElement('div');
// dashboardDiv.setAttribute("id", "dashboard_div");
var dashboardContainer = tableCell.appendChild(document.getElementById('dashboard_div'));
//dashboardContainer.className = 'chart';
var control = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control_div',
'options': {
'filterColumnIndex': 0,
'ui': {
'chartOptions': {
'height': 50,
'chartArea': {
'width': '75%'
},
'series': {
0: {
'targetAxisIndex': 0
},
1: {
'targetAxisIndex': 1
}
},
'vAxes': {
0: {
'title': 'Weight'
},
1: {
'title': 'smA'
}
}
}
}
},
});
var chart = new google.visualization.ChartWrapper({
'chartType': 'ComboChart',
'containerId': 'chart_div',
'options': {
'legend': {
'position': 'bottom',
'alignment': 'center',
'textStyle': {
'fontSize': 12
}
},
'explorer': {
'actions': ['dragToZoom', 'rightClickToReset'],
'axis': 'horizontal',
'keepInBounds': true
},
'hAxis': {
'title': 'X'
},
'pointSize': 3,
'series': {
0: {
'targetAxisIndex': 0
},
1: {
'targetAxisIndex': 1
}
},
'vAxes': {
0: {
'title': 'Weight'
},
1: {
'title': 'smA'
}
}
}
});
// build chart data table
var chartData = new google.visualization.DataTable();
chartData.addColumn('date', 'timestamp');
chartData.addColumn('number', 'weight');
chartData.addColumn('number', 'smA');
chartData.addRow([new Date(2016, 0, 1), 1, 123]);
chartData.addRow([new Date(2016, 1, 1), 6, 42]);
chartData.addRow([new Date(2016, 2, 1), 4, 49]);
chartData.addRow([new Date(2016, 3, 1), 23, 486]);
chartData.addRow([new Date(2016, 4, 1), 89, 476]);
chartData.addRow([new Date(2016, 5, 1), 46, 444]);
var dashboard = new google.visualization.Dashboard(dashboardContainer);
dashboard.bind(control, chart);
dashboard.draw(chartData);
}
});
});
});
});
table.draw(tableData, {
showRowNumber: false,
width: '100%',
height: '100%'
});
}
html,
body {
height: 100%;
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
}
.chart {
width: 500px;
height: 300px border: 1px solid black;
min-height: 200px;
}
.beige-background {
background-color: beige;
}
<html>
<head>
<script src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="table_div"></div>
<div id="dashboard_div" style="border: 1px solid #ccc">
<table class="columns">
<tr>
<td>
<div id="chart_div"></div>
<div id="control_div" style="padding-left: 2em; min-width: 250px"></div>
</td>
</tr>
</table>
</div>
</body>
</html>
I want the dashboard to be inserted into every row. What could be the issue?
Upvotes: 4
Views: 341
Reputation: 61232
the reason the dashboard only appears in the last row is because there is only one dashboard element.
as it goes through the loop, it appends and moves the dashboard to each cell,
ending up in the last row when the loop is finished.
rather than using an existing dashboard element,
let's add dashboard elements dynamically, one for each row.
here, we use an html template to store the dashboard content.
<!-- template: dashboard template -->
<script id="template-dashboard" type="text/html">
<div id="dashboard-{{Id}}" style="border: 1px solid #ccc;">
<table class="columns">
<tr>
<td>
<div id="chart-{{Id}}"></div>
<div id="control-{{Id}}" style="padding-left: 2em; min-width: 250px;"></div>
</td>
</tr>
</table>
</div>
</script>
then add the content to each table cell,
using the row index as the id for each dashboard and control.
// insert dashboard html
tableCell.insertAdjacentHTML('beforeEnd', renderTemplate('template-dashboard', {
Id: rowIndex
}));
then we can reference the newly created elements using the id...
// build dashboard
var dashboardContainer = tableCell.appendChild(document.getElementById('dashboard-' + rowIndex));
see following working snippet...
google.charts.load('current', {
'packages': ['corechart', 'controls', 'table', 'charteditor']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var tableData = new google.visualization.DataTable();
tableData.addColumn('string', 'Name');
tableData.addColumn('number', 'Salary');
tableData.addColumn('string', 'Chart');
tableData.addColumn('string', 'Test');
tableData.addRows([
['Mike', {
v: 10000,
f: '$10,000'
}, null, '5thFirst'],
['Jim', {
v: 8000,
f: '$8,000'
}, null, '5thSecond'],
['Alice', {
v: 12500,
f: '$12,500'
}, null, '5thThird'],
['Bob', {
v: 7000,
f: '$7,000'
}, null, '5thForth']
]);
var table = new google.visualization.Table(document.getElementById('table_div'));
google.visualization.events.addListener(table, 'ready', function() {
// table body
Array.prototype.forEach.call(table.getContainer().getElementsByTagName('tbody'), function(tableBody) {
// table rows
Array.prototype.forEach.call(tableBody.rows, function(tableRow, rowIndex) {
// table cells
Array.prototype.forEach.call(tableRow.cells, function(tableCell, cellIndex) {
// determine cell
if (cellIndex === (2)) {
// insert dashboard html
tableCell.insertAdjacentHTML('beforeEnd', renderTemplate('template-dashboard', {
Id: rowIndex
}));
// build dashboard
var dashboardContainer = tableCell.appendChild(document.getElementById('dashboard-' + rowIndex));
var control = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control-' + rowIndex,
'options': {
'filterColumnIndex': 0,
'ui': {
'chartOptions': {
'height': 50,
'chartArea': {
'width': '75%'
},
'series': {
0: {
'targetAxisIndex': 0
},
1: {
'targetAxisIndex': 1
}
},
'vAxes': {
0: {
'title': 'Weight'
},
1: {
'title': 'smA'
}
}
}
}
},
});
var chart = new google.visualization.ChartWrapper({
'chartType': 'ComboChart',
'containerId': 'chart-' + rowIndex,
'options': {
'legend': {
'position': 'bottom',
'alignment': 'center',
'textStyle': {
'fontSize': 12
}
},
'explorer': {
'actions': ['dragToZoom', 'rightClickToReset'],
'axis': 'horizontal',
'keepInBounds': true
},
'hAxis': {
'title': 'X'
},
'pointSize': 3,
'series': {
0: {
'targetAxisIndex': 0
},
1: {
'targetAxisIndex': 1
}
},
'vAxes': {
0: {
'title': 'Weight'
},
1: {
'title': 'smA'
}
}
}
});
// build chart data table
var chartData = new google.visualization.DataTable();
chartData.addColumn('date', 'timestamp');
chartData.addColumn('number', 'weight');
chartData.addColumn('number', 'smA');
chartData.addRow([new Date(2016, 0, 1), 1, 123]);
chartData.addRow([new Date(2016, 1, 1), 6, 42]);
chartData.addRow([new Date(2016, 2, 1), 4, 49]);
chartData.addRow([new Date(2016, 3, 1), 23, 486]);
chartData.addRow([new Date(2016, 4, 1), 89, 476]);
chartData.addRow([new Date(2016, 5, 1), 46, 444]);
var dashboard = new google.visualization.Dashboard(dashboardContainer);
dashboard.bind(control, chart);
dashboard.draw(chartData);
}
});
});
});
});
table.draw(tableData, {
showRowNumber: false,
width: '100%',
height: '100%'
});
}
// render html template
function renderTemplate(templateId, templateValues) {
var templateText; // html string to return
var templateValue; // html value
// get template html
templateText = document.getElementById(templateId).innerHTML;
// replace place holders with values
if (templateValues) {
for (var propHandle in templateValues) {
if (templateValues.hasOwnProperty(propHandle)) {
templateValue = '';
if (templateValues[propHandle] !== null) {
templateValue = templateValues[propHandle].toString();
}
if (templateValue.indexOf('$') > -1) {
templateValue = templateValue.replace(new RegExp('\\$', 'g'), '$$$');
}
if (templateText.indexOf('{{' + propHandle + '}}') > -1) {
templateText = templateText.replace(new RegExp('{{' + propHandle + '}}', 'g'), templateValue);
}
}
}
}
return templateText.trim();
}
html,
body {
height: 100%;
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
}
.chart {
width: 500px;
height: 300px border: 1px solid black;
min-height: 200px;
}
.beige-background {
background-color: beige;
}
<html>
<head>
<script src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="table_div"></div>
<!-- template: dashboard template -->
<script id="template-dashboard" type="text/html">
<div id="dashboard-{{Id}}" style="border: 1px solid #ccc;">
<table class="columns">
<tr>
<td>
<div id="chart-{{Id}}"></div>
<div id="control-{{Id}}" style="padding-left: 2em; min-width: 250px;"></div>
</td>
</tr>
</table>
</div>
</script>
</body>
</html>
Upvotes: 2
Reputation: 4419
I think your issue is coming from the following line:
var dashboardContainer = tableCell.appendChild(document.createElement('dashboard_div'));
What kind of element is "dashboard_div"? This creates the following:
<dashboard_div></dashboard_div>
I'm sure that's not what you want because you want to insert the chart in:
<div id="dashboard_div">
And these two things are not the same.
You could probably look at the result by inspecting the HTML using the developer console to see if the chart is really being inserted in the correct HTML tag.
Upvotes: 1