Node + Express + Swig / pass local json file to template

时间:2015-06-25 18:45:39

标签: javascript node.js express d3.js swig-template

I am a node noob, I am able to get express / swig to play nice, and display on screen, when I introduce my d3 code (which works by itself) the console comes back with Uncaught TypeError: Cannot read property 'forEach' of undefined(anonymous function) @ json:63event @ d3.js:504respond @ d3.js:1942 Things to note - the data.json is in the same directory as templates. Am I going about this the wrong way? Would it be better to do my d3 rendering inside node? If so, how do I pass that to a swig template etc? Edit - I noticed in the dev tools the json wasn't being retrieved, the but SVG renders. I commented out the following since express was hijacking the get. // app.get('/*', function (req, res) { // res.send("404 bro"); // }); Now a new error has risen, which is a good sign! GET http://localhost:3000/templates/data.json 404 (Not Found) Again, sorry I am somewhat of a node nooby. Update - here is my updated code var data = require('./templates/data/data.json'); console.log("====== Loaded Jason ======" + JSON.stringify(data)); app.get('/json', function(req, res){ res.render('line', {'title' : 'First Swig Template'}); res.sendFile(data); }); It comes back with Unhandled rejection TypeError: undefined is not a function Update - here is my updated code app.get('/json', function(req, res){ res.render('line', {'title' : 'First Swig Template'}); res.sendFile('data.json', { root: path.join(__dirname, '/templates/data') }); }); Which comes back with Error: Can't set headers after they are sent. The Json is now displaying on the screen though. Node code // Retrieve var MongoClient = require('mongodb').MongoClient; //Swig for template var swig = require('swig'); //consolidate -templating consolidation library var cons = require("consolidate"); // Express var express = require('express'); var app = express(); app.engine('html', cons.swig); app.set('view engine', 'html'); app.set('views', __dirname + '/templates'); app.get('/swig', function(req, res){ res.render('home', {'title' : 'First Swig Template'}); }); app.get('/json', function(req, res){ res.render('line', {'title' : 'First Swig Template'}); }); //setup routes app.get('/*', function (req, res) { res.send("404 bro"); }); //setup server var server = app.listen(3000, function () { var host = server.address().address; var port = server.address().port; console.log('Example app listening at http://%s:%s', host, port); }); // Connect to the db MongoClient.connect("mongodb://localhost:27017/linejson", function(err, db) { if(!err) { console.log("We are connected"); } var collection = db.collection('dummy'); // count records collection.count(function(err, count) { console.log("There are " + count + " records."); }); collection.find().each(function(err, doc) { if(doc != null) console.log("Doc from Each "); console.dir(doc); }); }); Html template + D3 code <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Data Visualization with D3 </title> <!-- Bootstrap CDN CSS --> <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"> <style> /* set the CSS */ body { font: 12px Arial;} path { stroke: steelblue; stroke-width: 2; fill: none; } .axis path, .axis line { fill: none; stroke: grey; stroke-width: 1; shape-rendering: crispEdges; } </style> </head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js"></script> <script> // Set the dimensions of the canvas / graph var margin = {top: 30, right: 20, bottom: 30, left: 50}, width = 600 - margin.left - margin.right, height = 270 - margin.top - margin.bottom; // Parse the date / time var parseDate = d3.time.format("%d-%b-%y").parse; // Set the ranges var x = d3.time.scale().range([0, width]); var y = d3.scale.linear().range([height, 0]); // Define the axes var xAxis = d3.svg.axis().scale(x) .orient("bottom").ticks(5); var yAxis = d3.svg.axis().scale(y) .orient("left").ticks(5); // Define the line var valueline = d3.svg.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.close); }); // Adds the svg canvas var svg = d3.select("body") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // Get the data // d3.json("data.json", function(data) { // data.forEach(function(d) { // d.date = parseDate(d.date); // d.close = +d.close; // }); d3.json("data.json", function(error, data) { data.forEach(function(d) { d.date = parseDate(d.date); d.close = +d.close; }); // Scale the range of the data x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([0, d3.max(data, function(d) { return d.close; })]); // Add the valueline path. svg.append("path") .attr("class", "line") .attr("d", valueline(data)); // Add the X Axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); // Add the Y Axis svg.append("g") .attr("class", "y axis") .call(yAxis); }); </script> </body> </html>

2 个答案:

答案 0 :(得分:1)

app.use(express.static(__dirname + '/data'));

以下行修好了!感谢您的投入!

答案 1 :(得分:0)

由于您使用node来处理与服务器的交互,因此您提供了通过节点的文件路径。类似于以下内容。

app.get('/templates/data', function(req, res){
    res.sendfile(data.json);
});

然后将文件放在/template/data/data.json路径中。

希望这有帮助。