score:1

Accepted answer

My solution require you to install two additional modules:

npm install -save express-handlebars & npm install -save pg-promise

After that in the app.js you could connect to your postgresql server and parse the data through handlebar helpers, here's all the code for that.

app.js

const express = require('express');
const exphbs  = require('express-handlebars');
const pgp     = require('pg-promise')(/*options*/);

var app = express();

dbLoad();

function dbLoad() {

  var connect = {
    host: 'localhost',
    port: 5432,
    database: 'postgres',
    user: 'postgres',
    password: 'YourPassword'
  };

  var db = pgp(connect); 

  db.query({
    text: 'SELECT * FROM table1',
    values: [],
    rowMode: 'array'
  })
  .then(data => {
    var arr = [];
    data.forEach(function(d) {
      var i = 0
      arr.push({
        age: d[i], 
        population: d[i + 1]
      })
      i++
    })

    pageLoad(arr); // Function call to load the page

  })
  .catch(reason => {
    console.log(reason)
  });

}

function pageLoad(data) {

  var hbs = exphbs.create({
    helpers: {
      sqlData: function () { return JSON.stringify(data); }
    }
  });

  app.engine('handlebars', hbs.engine);
  app.set('view engine', 'handlebars');

  app.get('/', function (req, res, next) {
    res.render('home', {

      showTitle: true,
    });
  });

  app.listen(3000);

}

This assumes that you have the data on your server called table1 with the exact same data structure as your csv.

Then you should create a folder called views in the same folder as your app.js and create a file called home.handlebars (this is replacement for your index.html)

In this file you'll want to call your data like this {{sqlData}} and parse it.

home.handlebars

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="//d3js.org/d3.v3.min.js"></script>
<title></title>
</head>
<body>

<div id="chart"></div>

</body>

<script>

var init = JSON.parse("{{sqlData}}".replace(/&quot;/g,'"').replace(/&lt;/,''))

chart(init);

function chart(data) {

  var width = 960,
      height = 500,
      radius = Math.min(width, height) / 2;

  var color = d3.scale.ordinal()
      .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

  var arc = d3.svg.arc()
      .outerRadius(radius - 10)
      .innerRadius(radius - 70);

  var pie = d3.layout.pie()
      .sort(null)
      .value(function(d) { return d.population; });

  var svg = d3.select("#chart").append("svg")
      .attr("width", width)
      .attr("height", height)
    .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    var g = svg.selectAll(".arc")
        .data(pie(data))
      .enter().append("g")
        .attr("class", "arc");

    g.append("path")
        .attr("d", arc)
        .style("fill", function(d) { return color(d.data.age); });

    g.append("text")
        .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
        .attr("dy", ".35em")
        .text(function(d) { return d.data.age; });

}

</script>
</html>

And that should be it.

NOTE I'm not an expert in node.js and there could be some serious security flaw with doing it this way if you're concerned about that, I'd suggest going though the express.js api and look through a proper way to get json object directly from the app.js without all the hacky string replacement I did in this solution.

EDIT:

Reduced the stringreplacement to a single line of code:

var init = JSON.parse("{{sqlData}}".replace(/&quot;/g,'"').replace(/&lt;/,''))

score:0

Wrap your d3 code into a function which gets called whenever you fetched your data as json by express.js call donut(json) like

donut.js:

function donut(json) {
  ...
  var g = svg.selectAll(".arc")
      .data(pie(json))
    .enter().append("g")
      .attr("class", "arc");

...
}

or use d3.json to fetch json from the server and pass in the URL like

...
d3.json(data_url, type, function(error, data) {
  if (error) throw error;

  var g = svg.selectAll(".arc")
    .data(pie(data))
    .enter().append("g")
    .attr("class", "arc");
...

Related Query