Im trying to figure it out for past 6 hours, but Im out of ideas..
What Im trying to accomplish:
I want to display a JSON data that looks like this
movie {title: " xxxxx", seed: "number", url: "zzzzzzzzz"}
I want to display it on my Node server(via jade), but what I accomplished till now is to send it from the website to my node server via POST request using this code:
My JS script
var http = new XMLHttpRequest();
var url = "http://localhost:8080/";
var params = arr; <------ My JSON data
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(params);
After using above code in my google chrome developer tools on the website I actually have that data, I receive the JSON array in my node, here is my node code:
My app.js node server
const http = require("http");
const express = require('express');
const app = express();
const myParser = require('body-parser');
app.set('views', __dirname + '/views')
app.set('view engine', 'jade')
app.use(express.static(__dirname + '/public'))
app.use(myParser.urlencoded({ extended: false }));
app.use(myParser.json())
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use(allowCrossDomain);
app.get('/', function (req, res, next) {
res.render('index');
})
app.get('/tl', function (req, res, next) {
res.render('tl');
})
app.post("/", function (req, res) {
response = {
first_name: req.body
};
console.log('SHOW ME BODY')
console.log(req.body);
res.send('You sent: this to Express');
});
app.listen(8080);
And this is what Im receiving in my node command prompt:
{ '[{"title":" SOME-MOVE-TITLE","seed":"NUMBER","url":"https://SOMEURLS.COM', etc. etc. etc.
And finally here is my layout.jade file
doctype
html
head
title Bolo Node Server
link(rel="stylesheet", type="text/css", href="stylesheet/style.css")
body
header
h1 My Site
block content
footer
p Running on node with Express, Jade and Stylus
And index.jade
extend layout
block content
p= 'Block content works'
script.
if req.body != undefined
div(id='data')= req.body
I really run out of ideas on how to display the json array Im receiving...help me out please
Update
My index.jade
extend layout
block content
p= 'Block content works'
div(id='data')
pre
test= jsonString
My app.js looks now like this:
app.get('/', function (req, res, next) {
res.render('index');
})
app.post("/", function (req, res) {
// Get string representation
var jsonString = JSON.stringify(req.body || {}); // use JSON.stringify(req.body || {}, null, 2) for formatted JSON
console.log(jsonString);
res.render('index', {test: jsonString});
//res.send('You sent: this to Express');
});
I see the data in my node command prompt, but I dont see it on my local website http://localhost:8080/ the div(id='data') is showing me empty.. nothing, how do I get the jsonString there?? I want it to show me the data on my local website..
**
UPDATE
**
I ended up just putting the data into the sqlite3 database and then retrieving the data via GET request and finally putting it into my jade template. I thought I can go around and not use sqlite3 but I couldnt figure out how.
When you say that you want to display the json, if you just want to see the contents of the json you can use res.json.
app.post("/", function (req, res) {
// Send back the request body if present or else, an empty object
res.json(req.body || {});
});
If you want it to be displayed inside a template, you can get a string representation of the json using JSON.stringify(req.body) and render that in your template by passing it to it as a local variable.
app.post("/", function (req, res) {
// Get string representation
var jsonString = JSON.stringify(req.body || {}); // use JSON.stringify(req.body || {}, null, 2) for formatted JSON
res.render('jsonView',{jsonString});
});
And in your template:
div(id='data')
pre
code = jsonString
You should pass the data in the template.
res.render('index', {data: 'data'});
And show it with:
data = data
p #{data}
First you should parse your incoming data, as is application/x-www-form-urlencoded. You'll need to JSON.parse req.body first and encode your response as json too
app.post("/", function (req, res) {
var response = try { JSON.parse(req.body) } catch(e) { console.error('Invalid Data') };
res.json(response || {});
});
You could also send your data as 'application/json' from you client JS and save receive a JSON directly to the req.body.
Hope it helps
UPDATE (if you want to append new data via async requests on the client)
In this post you can see the use of XmlHttpRequest with jquery $.ajax() which is basically the same concept of async requests after the DOM is rendered on your server.
Imagine the step 3 being your Jade rendered HTML
I ended up just putting the data into the sqlite3 database and then retrieving the data via GET request and finally putting it into my jade template. I thought I can go around and not use sqlite3 but I couldnt figure out how.
Here is the code
app.post("/", function (req, res) {
var jsonString = JSON.stringify(req.body || {});
db.serialize(function () {
var stmt = db.prepare("INSERT INTO movies (id, title, seed, url) VALUES (?,?,?,?)");
for (var i = 0; i < req.body.length; i++) {
var d = new Date();
var data = req.body;
var n = d.toLocaleTimeString();
stmt.run(i, req.body[i].title, req.body[i].seed, req.body[i].url);
}
stmt.finalize();
});
res.send('You sent: this to Express');
});
Retrieving the data from the database
app.get('/tl', function (req, res, next) {
db.all('select * from movies', function (err, rows) {
if (err)
return next(err);
var dataO = [];
rows.forEach(function (row) {
dataO.push(row);
})
res.render('tl', { dataO: dataO });
})
})
Related
I need to display data that gets posted after rendering view with res.render() in get. When I use <% date %> my view throws an error saying that date is not defined and I know this happens because my value does not exist before rendering the view and its getting set after. So how do I set this variable to be displayed in my ejs file before or after my view gets rendered?
I have tried a few things like using res.send(), using another get() inside my post() and even creating a partial view but nothing works. I dont want to click any buttons to be able to do this and if its only possible with clicking well then. I know you cant use res.send() on the same view twice.
My post XMLHttpRequest is executed when the page loads in javascript to set my date variable and send it to my node.js file then I use express to fetch it. My node.js code is the following:
app.get('/', function (req, res) {
res.render('index', {
time: time,
views: visitors,
mobileViews: mobileVisitors,
});
}
app.post('/', function(req, res){
console.log('working');
getInfo = req.body;
console.log(getInfo);
//getInfo.date = 1
res.render('index', {dataTest: getInfo.date}); //this doesnt work
//OR res.send({dataTest: getInfo.date}); doesnt work
//OR app.get('/', function (req, res) {res.render ... doesnt work
}
My ejs view is:
<h1 class="test">test <%= dataTest %></h1>
My js file:
var waitForEl = function (selector, callback) {
if (jQuery(selector).length) {
callback();
} else {
setTimeout(function () {
waitForEl(selector, callback);
}, 100);
}
};
waitForEl(".daterangepicker", function () {
var element = document.querySelector('.ranges ul').childNodes[0].childNodes[0].data.toString();
console.log(element);
var date = 0;
date = sendData(date, element);
var obj = JSON.stringify({date: date});
console.log(obj);
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:4000", true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send(obj);
});
function sendData(date, element) {
if(element == 'Today') {
date = 1;
}
return date;
}
try this :
const bodyParser =require('body-parser');
const urlencodedParser = bodyParser.urlencoded({ extended: false });
app.get('/', function (req, res) {
res.render('index', {
time: time,
Views: visitors,
mobileViews: mobileVisitors,
});
}
app.post('/',urlencodedParser,function(req, res){
console.log('working');
getInfo = req.body;
console.log(getInfo);
res.render('index', {getInfo: getInfo});
}
you need also a midlleware to handle post method in express app
npm i body-parser
it's better to use the object's key name as its value name to ease cycling through the properties
then in your ejs view use :
<%= getInfo.date %>
there is an = sign,don't forget it.
What I see is the first time you are trying to get "/" you don't have agetInfo.date
So make a getInfo.date = Date.now()
Or getInfo.date = new Date()
And pass it in into your initial get('/') call.
const bodyParser =require('body-parser');
const urlencodedParser = bodyParser.urlencoded({ extended: false });
app.get('/', function (req, res) { res.render('index', { time: time, Views: visitors, mobileViews: mobileVisitors, getinfo: getInfo}); }
app.post('/',urlencodedParser,function(req, res){ console.log('working');
getInfo = req.body; console.log(getInfo); res.render('index', {getInfo: getInfo}); }.
on the other hand you may also choose to make the getInfo.date = null or getInfo.date = ''
And check in your ejs with if condition if(getinfo.date){<=getinfo.date>}
Trying from mobile. Hope this solves
I have question about route to get both request from param and body
My route is to delete user. It looks like this:
router.delete("/delete/:id",middleware, async (req, res) => {
//firstly, I get param:
var userId = req.params.id || '';
//if emty, it will get request from body
if(!userId){
const listId = req.userIds
}
});
I perform request but it shows error: Cannot DELETE /api/users/delete
http://localhost:5000/api/users/delete/
Can you explain me what wrong with my issue?
Based on your latest comment you will need a route for collection delete as well as the model route. Here is some "pseudocode":
// model form
router.delete("/delete/:id",middleware, async (req, res) => {
var userId = req.params.id
// made up backend service - add error handling, etc
await dataService.users.delete(userId);
res.sendStatus(200); // again with error stuff
});
// collection form
router.delete("/delete",middleware, async (req, res) => {
var userIds = req.body.userIds; // assumes use of bodyParser
for (userId in userIds) {
// made up backend service - add error handling, etc
await dataService.users.delete(userId);
res.sendStatus(200); // again with error stuff
}
});
I'm making an API call in a POST route but for some reason, I can't pass the JSON data through res.render in the POST route. So I'm thinking about passing the JSON object to GET route so I can render it to the right client page.
Heres my GET and POST routes:
router.get('/bookDetails', (req, res) => {
res.render('bookDetails');
});
router.post('/bookDetails', (req, res) => {
let ID = req.body.ID;
request('https://www.googleapis.com/books/v1/volumes/' + ID, (err, response, body) => {
if(!err && response.statusCode == 200){
let bookdata = JSON.parse(body);
res.render('bookDetails', {bookdata: bookdata});
}else{
console.log(err);
}
});
});
I can't read the bookdata in my bookDetails.ejs file? Is there another way pass this data to the page?
On semantic, it should be a GET router to display something about the ID resource.
router.get('/bookDetails/:id', (req, res) => {
let resource = await fetchResourceById
res.render('bookDetails', resource);
});
also, you can define a middleware function to reuse the fetchResource logic, as following:
function fetchResourceMiddleware(){
return function(req, res, next){
var id = req.query.id || req.body.id
if(id){
req.resource = await fetchResource(id)
}
next()
}
}
reuse the middleware function for GET and POST router:
function renderResource(req, res){
res.render('bookDetails', req.resource);
}
router.get('/bookDetails/:id', fetchResourceMiddleware(), renderResource)
router.post('/bookDetails', fetchResourceMiddleware(), renderResource)
hope helpful, good luck!
After post, your get method will run.
In the get method, you are not sending any data to ejs template, so it will not detect it.
You should redirect in post method, it is bad idea sometimes,
I'm building my first node/express app and am following this tut.
I am at a point where I am trying to get all JSON data and put it in an array to be sent to the template and rendered. When I try to run the app via CLI, I get the following error:
Directory Structure
The data output at the var blogsurlall location
hellotest.js
var routes = require('./routes/index');
var express = require('express');
var app = express();
var request = require("request");
var blogsurlall = "https://[JSON export URL location configured in a Drupal 8 view]";
app.set('view engine','ejs');
var server = app.listen (2000, function(){ console.log('Waiting for you on port 2000'); });
/* Get all global blogs data */
request({
url: blogsurlall,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
blogsdata_all = body;
}
// Create blogs array for footer.
var blogs = [];
// Fill up the array with blogs.
blogsdata_all.blogs.forEach(function(item){
blogs = blogs.concat(item);
});
app.locals.blogsdata = blogs;
});
app.use('/', routes);
index.js
var express = require('express');
var routes = express.Router();
routes.get('/', function(req, res){ res.render('default',{title: 'Home', body: 'blogsdata'}); });
routes.get('/about-us', function(req, res){ res.send('<h1>Lucius Websystems</h1>Amsterdam, The Netherlands'); });
routes.get('/about/:name?', function(req, res){ var name = req.params.name; res.send('<h1>' +name +'</h1>About text'); });
/* GET Blog detail page. */
routes.get('/blog/:blogid', function(req, res, next) {
// Place json data in a var.
var blogsdata = req.app.locals.blogsdata;
// Create array.
var blogItem = [];
// Check and build current URL
var currentURL = '/blog/' + req.params.blogid;
// Lop through json data and pick correct blog-item based on current URL.
blogsdata.forEach(function (item) {
if (item.title == currentURL) {
blogItem = item;
}
});
if (blogItem.length == 0) {
// Render the 404 page.
res.render('404', {
title: '404',
body: '404'
});
} else {
// Render the blog page.
res.render('blog-detail', {
blog: blogItem
});
}
});
module.exports = routes;
From the CLI error, it appears no blog data is even returned to be read into the array.
I have carefully gone through the tutorial several times and I think there are steps that may be implied that I am missing.
Can someone please help me understand how to get the blog data so that it can be read into the array and output to my template?
Also open to troubleshooting suggestions in comments.
Thanks for reading!
The error is raising in this line:
blogsdata_all.blogs.forEach(function(item){
As the error says, blogs is undefined.
If there is an error in the request or status code isn't 200, the body is not assigned to the variable, but you are not finishing the execution, so the variable in that case would be undefined.
Other possible problem is the json received doesn't have blogs as key of the body.
Check this both things and let us know if you found the problem
I'm handling a POST request like so:
app.post('/somepage', function (req, res) {
var post_data = req.body;
});
Here, req.body already is a JavaScript object (I've tried console.log(req.body) and got [object Object] in the server's console). I would like to get the original POST data string that was sent with the HTTP request. Is that possible?
Note: I use this middle-ware:
app.use(express.json());
app.use(express.urlencoded());
Here's one solution that might work:
// ...
app.use(function(req, res, next) {
var buffer = '';
req.on('data', function(data) {
buffer += data.toString();
}).on('end', function() {
req.bodyraw = buffer;
});
next();
});
app.use(express.json());
app.use(express.urlencoded());
// ...
app.post('/somepage', function (req, res) {
var rawpost = req.bodyraw;
});
It should be safe since the json and urlencoded middleware add (data) event handlers immediately, but it would be better if the first middleware did pause() AND if the json and urlencoded middleware did resume() when seeing an explicitly paused stream -- this would guarantee no data could be lost.
You are searching for the 'body-parser' middleware. You have several options to get the body, including as the raw buffer or as text.
app.post('/somepage', function (req, res) {
var post_data = req.body.toString();
});