Render JSON data onto ejs view with Expressjs - json

I am trying to get 2 values from a JSON file on to the webpage.
obj["fruit"] and obj["thyroid"]. I use ejs as the template view engine and expressjs.
The below method says "fruit" and "thyroid" are undefined. The console.log works though.
app.post('/top', function (req, res) {
var obj;
fs.readFile('./object.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data);
console.log(obj["fruit"]);
console.log(obj["thyroid"]);
});
res.render(
'disp.ejs',
{
food: obj["fruit"]
name: obj["thyroid"]
}); // render
});

fs.readFile(path[, options], callback) is the asynchronous way to read a file. The way your code is setup node will start reading the file and immediately then call res.render before the file data is finished reading.
If you put the res.render inside the callback it will only be called when the file is finished reading and the data variable has what you need.
for example:
app.post('/top', function (req, res) {
var obj;
fs.readFile('./object.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data);
console.log(obj["fruit"]);
console.log(obj["thyroid"]);
res.render(
'disp.ejs',
{
food: obj["fruit"]
name: obj["thyroid"]
}); // render
});
});

Related

ReferenceError when trying to use a variable in an EJS template file

I'm having a heap of trouble just trying to get an EJS template file to recognise a variable that stores the rows of an SQLite3 table query in a corresponding .js file. I get a ReferenceError for the variable I used in the EJS file when launching the server and trying to access that route.
For context it's a micro blog project where I'd like authors to have the ability to save draft articles in to a database and for the user to be able to come back and modify or publish them later.
Here's my 'author.js' file:
// Author Page
const express = require("express");
const router = express.Router();
const assert = require('assert');
/**
* #desc retrieves draft articles
*/
router.get("/author-home", (req, res, next) => {
//Use this pattern to retrieve data
//NB. it's better NOT to use arrow functions for callbacks with this library
global.db.all("SELECT * FROM draftArticles", function (err, rows) {
if (err) {
next(err); //send the error on to the error handler
} else {
res.json(rows);
}
});
});
/**
* #desc Renders the author page
*/
router.get("/author", (req, res) => {
res.render("author-home", data);
});
module.exports = router;
In my 'author-home.ejs' file, I'm trying to insert various article properties in a element like so:
<td><% data[0].article_title %> </td>
<td><% data[0].article_subtitle %> </td>
...etc.
Can anyone tell me what I'm doing wrong? I can also post the code for my 'index.js' file if that's helpful. Many thanks in advance
EDIT:
After some suggestions were sent and the scope issue of the 'data' variable was highlighted, I corrected my code in author.js (at least, I believe so) to the following:
// Author Page
const express = require("express");
const router = express.Router();
const assert = require('assert');
router.get('/author-home', (req, res, next) => {
global.db.all('SELECT * FROM draftArticles', function (err, rows) {
if (err) {
console.log("No data found.")
next(err); //send the error on to the error handler
return;
}
res.render('author-home', { data: rows });
});
});
module.exports = router;
However, I still receive a referenceError when trying to access data in my EJS file.
I also tried, as was suggested, to pass static data like so:
let dummyData = "This is test data";
router.get('/author-home', (req, res, next) => {
res.render('author-home', { data: dummyData });
});
Also receiving a referenceError.
This is because you have not defined "data". You need to define it if you want to send an array you can use
How can I pass an array to an ejs template in express?
your code should be like..
// Author Page
const express = require("express");
const router = express.Router();
const assert = require('assert');
router.get('/author-home', (req, res, next) => {
global.db.all('SELECT * FROM draftArticles', function(err, rows) {
if (err || !rows || !rows.length) {
console.log("No data found.")
// also try to log rows here to see what you are getting. does the "rows" have atricle_title etc attributes or not?
next(err || new Error("No Data found!")); //send the error on to the error handler
return;
}
res.render('author-home', {
data: rows
});
});
});
module.exports = router;

NodeJS retrieve JSON and serve to EJS template

my purpose is to get a JSON and serve it to an EJS file.
This is my code:
//server.js
users = require('./controllers/users.js');
global.app_root = path.resolve(__dirname);
app.get('/users', function(req, res) {
res.render('partials/users', {
data: users.retrieve_users
});
})
//users.js
var fs = require("fs");
exports.retrieve_users = function (req, res) {
fs.readFile(app_root + "/config/" + "users-list.json", 'utf8', function (err, data) {
res.end(data);
});
}
//users.ejs
<body>
<%= data %>
</body>
But as output of this code inside the body I see literally this string:
'function (req, res) {
fs.readFile(app_root + "/config/" + "users-list.json", 'utf8', function (err, data) {
res.end(data);
});
}'
The problem is that your data is coming asynchronous and you don't wait for them before the rendering. In fact right now you dont even run the users.retrieve_users function, you just getting back the function declaration and express renders it as string! Change your code to this.
//server.js
users = require('./controllers/users.js');
global.app_root = path.resolve(__dirname);
app.get('/users', function(req, res) {
//a method that get thr user-list data and renders it
users.retrieve_users()
.then(function(users){
res.render('partials/users', {
data: users
});
})
.catch(function(err){
res.status(500).send({ error: 'something blew up' });
})
})
//users.js
var fs = require("fs");
exports.retrieve_users = function () {
//function that returns user-list in promise
return new Promise(function(resolve,reject){
fs.readFile(app_root + "/config/" + "users-list.json", 'utf8', function (err, data) {
if(err) return reject(err)
resolve(data);
});
})
}
//users.ejs
<body>
<%= data %>
</body>

Analyzing json using Watson API Nodejs

I would like to analyze a JSON file I dynamically create with Watson's tone analyzer. I would like it to read the file, then analyze it.
How can I make the tone_analyzer.tone method read the file? Thank you.
app.get('/results', function(req, res) {
// This is the json file I want to analyze
fs.readFile('./output.json', null, cb);
function cb() {
tone_analyzer.tone({
// How can I pass the file here?
text: ''
},
function(err, tone) {
if (err)
console.log(err);
else
console.log(JSON.stringify(tone, null, 2));
});
console.log('Finished reading file.')
}
res.render('results');
})
Your callback is missing a couple of arguments (error, data) (see the node fs documentation for more info). Data is the content of your file and would go where you are sending the text.
Try something like this:
app.get('/results', function(req, res) {
// This is the json file I want to analyze
fs.readFile('./output.json', 'utf8', cb);
function cb(error, data) {
if (error) throw error;
tone_analyzer.tone({
// How can I pass the file here?
text: data
},
function(err, tone) {
if (err)
console.log(err);
else
console.log(JSON.stringify(tone, null, 2));
});
console.log('Finished reading file.')
}
res.render('results');
})
Thanks to user Aldo Sanchez for his tip. I converted the input into JSON first since fs was returning it in the form of buffer data. Also, I made it search for the specific value in the key/value pair and return that content, instead of returning the whole string. This can be directly inputted to Watson's tone analyzer.
var data = fs.readFileSync('./output.json', null);
JSON.parse(data, function(key, value) {
if (key == "message") {
cb(value);
}
function cb(value, err) {
if (err) throw err;
tone_analyzer.tone({
text: value
},
function(err, tone) {
if (err)
console.log(err);
else
console.log(tone);
});
}
console.log('Finished reading file.')
});

NodeJS: saving JSON to MongoDB

I am trying to get JSON from an API and store it into a MongoDB database.
Obviously, it doesn't work. My app seems to hang around the point where I try to save the data to the database. Please advise what to do.
Here's my code:
var express = require('express');
var router = express.Router();
var http = require('http');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/zak", {native_parser : true});
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
var site = 'http://www.vsechnyzakazky.cz/api/v1/zakazka/?format=json&limit=2';
function getData(cb) {
http.get(site, function(res) {
// explicitly treat incoming data as utf8 (avoids issues with multi-byte chars)
res.setEncoding('utf8');
// incrementally capture the incoming response body
var body = '';
res.on('data', function(d) {
body += d;
});
// do whatever we want with the response once it's done
res.on('end', function() {
try {
var parsed = JSON.parse(body);
} catch (err) {
console.error('Unable to parse response as JSON', err);
return cb(err);
}
// pass the relevant data back to the callback
cb(
parsed.objects
);
});
}).on('error', function(err) {
// handle errors with the request itself
console.error('Error with the request:', err.message);
cb(err);
});
}
function writeData (data, allGood){
// couple of visual checks if all looking good before writing to db
console.log('writing');
console.log(typeof data);
console.log(data);
db.collection('zakazky').save(data, function(error, record){
if (error) throw error;
console.log("data saved");
});
}
function allGood(){console.log('all done');}
getData(writeData);
// ---------------------
module.exports = router;
You are calling the save() instead of insert(). Change this part and it will work:
// this should call insert, not save
db.collection('zakazky').insert(data, function(error, record){
if (error) throw error;
console.log("data saved");
});

how to print json array in html return by node.js

i return the array from node.js
reading xml content from txt file and store in array send to html page using ajax method how do this task.
xml2js = require('xml2js');
fs = require('fs');
var arr={};
var parser = new xml2js.Parser();
fs.readFile('D:/test.txt', function(err, data) {
parser.parseString(data, function (err, result) {
arr=result.Cluster.Array[0].String;
});
});
app.get('/test', function(req, res, next) {
res.json({ message: arr }); //passing array data
});
how to display in html page current i used. But i get whole data in console log not able to display in html page get message undefined :
$.ajax({
url: '/test',
complete: function(data) {
JSON.stringify(data);
console.log(data.message);
// document.write(data.message);
for(i=0;i<data.length;i++)
{
document.write(data.message[i].Val);
$('#did').append('<h1>'+data.message[i].Name+'</h1>');
}
}
use a ReadStream, and stream it into your httpResponse
stream = fs.createReadStream "path/to/file.json"
stream.pipe(res)