Omri
Omri

Reputation: 95

Embedding a dashboard inside a google chart table

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: enter image description here

Only replacing the line chart with a dashboard chart like the following: enter image description here

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

Answers (2)

WhiteHat
WhiteHat

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

Aerials
Aerials

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.


References:

Upvotes: 1

Related Questions