skip to Main Content

I want to use google-charts. The quick-start example given here:
https://developers.google.com/chart/interactive/docs/quick_start
explicitly defines the data within the HTML file. I’d like to do this dynamically using EJS templating. My issue is how do I pass the data into drawChart()

My chart.js and chart.ejs files are below

chart.js

import { dirname } from "path";
import express from "express"
import { fileURLToPath } from "url";
// A note on where this project left off on 8/14/2023
// The goal is to use Google Chart as a dashboard
// showing database data as a collection of charts and graphs
// The chart.ejs file is used as the template to render the page
// One key hurdle is how to get the data into the .ejs file so it
// can be used by the file's javascript code and not just the html
// code.
//
// For example, 
// <body>
// <% console.log(graphs.name) %>
// <% console.log(graphs.myData) %>
// </body>
// renders just fine on the page

const __dirname = dirname(fileURLToPath(import.meta.url));
let myData = [
    ['Mushrooms', 3],
  ['Onions', 1],
  ['Olives', 1],
  ['Zucchini', 1],
  ['Pepperoni', 2],
  ['Pineapple',12],
  ['Green Peppers',22]
  ]
  
  let myGraph ={}
  myGraph.name="First Chart"
  myGraph.myData=myData

  const app = express();

  app.get('/', (req, res) => {
    const templatePath = __dirname+"/views/chart.ejs";
    res.render(templatePath,{ graphs: myGraph })
    
});

  app.listen(3000, () => {
    console.log("Server running on localhost:3000")
  });

Here is my chart.ejs file:

<!DOCTYPE html>
<html lang="en">

</html>
<html>

<head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
        google.charts.load('current', { 'packages': ['corechart'] });
        google.charts.setOnLoadCallback(drawGraphs);

        function drawGraphs() {
            console.log("Entered drawGraphs()")
            console.log(graphs)
            appendDivToBody(graphs.name, 'width: 1200px; height: 500px');
            graphs.forEach(g => {
             appendDivToBody(g.name, 'width: 1200px; height: 500px');
             drawGraph(g.name, g.myData);
            });
        }

        function drawGraph(graphName, graphData) {
            var data = new google.visualization.DataTable();
            data.addColumn('string', 'Toppings');
            data.addColumn('number', 'Slices');
            data.addRows(graphData);
            var options = {
                title: `${graphName}`,
                'width': 500,
                'height': 300
            };
            var chart = new google.visualization.PieChart(document.getElementById(graphName));
            chart.draw(data, options);
        }

        function appendDivToBody(id, style) {
            var div = document.createElement('div');
            div.id = id;
            div.style = style;
            document.getElementsByTagName('body')[0].appendChild(div);
        }

    </script>
</head>

<body>
    <% console.log(graphs.name) %>
    <% console.log(graphs.myData) %>
    <p>
        <!-- HTML content goes here -->
        Hello
    </p>
    <ul>
        <%graphs.myData.forEach((item)=> { %>
            <li>
                I had <%=item[1] %> slices of <%=item[0]%> pizza </br>
            </li>
            <%})%>
    </ul>
</body>
</body>

</html>

It produces this output only without the chart.

Hello

I had 3 slices of Mushrooms pizza
I had 1 slices of Onions pizza
I had 1 slices of Olives pizza
I had 1 slices of Zucchini pizza
I had 2 slices of Pepperoni pizza
I had 12 slices of Pineapple pizza
I had 22 slices of Green Peppers pizza

A look at the consol.log() output using Chrome-Inspect ==> I see the error:

Uncaught (in promise) ReferenceError: graphs is not defined

This indicates that drawGraphics() does not see the graphs JSON object. How can I accomplish this?

2

Answers


  1. Chosen as BEST ANSWER

    That was perfect. I saw the post you referenced but was unsure where to put the line of code. In VScode, the syntax was highlighted as being in error. This led me to think that the line of code did not belong in the section. Thanks for being explicit in your answer!

    enter image description here


  2. based on this answer: ejs to render a JSON
    you should be able to write the json to the page in a variable as follows…

    var graphs = <%- JSON.stringify(graphs) %>;
    

    here…

    function drawGraphs() {
      var graphs = <%- JSON.stringify(graphs) %>;  // write json here
      appendDivToBody(graphs.name, 'width: 1200px; height: 500px');
      graphs.forEach(g => {
       appendDivToBody(g.name, 'width: 1200px; height: 500px');
       drawGraph(g.name, g.myData);
      });
    }
    

    then the rest of the code should be close to working

    google.charts.load('current', { 'packages': ['corechart'] });
    google.charts.setOnLoadCallback(drawGraphs);
    
    function drawGraphs() {
        var graphs = <%- JSON.stringify(graphs) %>;
        appendDivToBody(graphs.name, 'width: 1200px; height: 500px');
        graphs.forEach(g => {
         appendDivToBody(g.name, 'width: 1200px; height: 500px');
         drawGraph(g.name, g.myData);
        });
    }
    
    function drawGraph(graphName, graphData) {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Toppings');
        data.addColumn('number', 'Slices');
        data.addRows(graphData);
        var options = {
            title: graphName,
            width: 500,
            height: 300
        };
        var chart = new google.visualization.PieChart(document.getElementById(graphName));
        chart.draw(data, options);
    }
    
    function appendDivToBody(id, style) {
        var div = document.createElement('div');
        div.id = id;
        div.style = style;
        document.getElementsByTagName('body')[0].appendChild(div);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search