Receiving json with list using nodejs e express - javascript

I'm trying to receive a json with list of items in a nodejs code, but it doesn't works.
router.post('/', (req, res) => {
models.sequelize.transaction().then(transation => {
let entity = req.body;
If req.body it's just an element, works perfectly well.

Add app.use(bodyParser.json()); to your code, make sure the JSON could be parsed correctly.

I needed use JSON.stringfy first, then JSON.parse.
router.post('/', (req, res) => {
models.sequelize.transaction().then(transation => {
let entities = JSON.stringify(req.body, null, 2);
entities = JSON.parse( entities ); here
Probably it's not the best way, but works for me.

Related

how to display data to ejs from API (express js)

Using express js, i want to render json that has been produced by my to ejs file.
here is my controller that produce json
const getAllQuotes = asyncWrapper(async (req, res) => {
const quotes = await qSchema.find({});
res.status(200).json({ quotes });
});
I want to pass the JSON from controller to my router below, then what my router does is bring the data and show the data to admin page
adminRoute.get('/', async (req, res) => {
//what should i type here?
res.render("admin")
})
or maybe my question is about how the data can be thrown/passed in between js file
Don't make HTTP requests from your server back to your server.
You have a function that gets your data. Use that function.
adminRoute.get('/', async (req, res) => {
const quotes = await qSchema.find({});
res.render("admin", { quotes });
})

How to make query request using ExpressJS

what command I should write in ExpressJS file just so that exposes a single HTTP endpoint (/api/search?symbol=$symbol&period=$period)
Working
app.get('/api/search/', (req, res) => {
res.send(req.query)
})
Not working:
app.get('/api/search?symbol=$symbol&period=$period', (req, res) => {
res.send(req.query)
})
app.get('/api/search?symbol=$symbol&period=$period', (req, res) => {
res.send(req.query)
})
In place of this, you have to write below code
const note = require('../app/controllers/note.controller.js');
// Create a new API CALL
app.get('/comment/get', note.index); // In socket.controller.js i have function with the name of index
//note.controller.js file code
exports.index = (req, res) => {
var requestTime = moment().unix();
req.body = req.query;
console.log(req.body); // you will able to get all parameter of GET request in it.
}
Let me know if i need to explain more about
And for sample code of express for API you can view this...
https://github.com/pawansgi92/node-express-rest-api-sample
What I think you're looking for is this:
app.get('/api/search', (req, res) => {
let symbol = req.query.symbol
let period = req.query.period
})
So when you navigate to /api/search?symbol=foo&period=bar
req.query.symbol is "foo"
and req.query.period is "bar"

Node/Express - use API JSON response to (server-side) render the app

Preamble: I'm new to web dev so maybe this might be a very basic question for you vets.
I'm using MVC architecture pattern for this basic app. I've models (MongoDB), views (Express Handlebars), and controllers (functions that take in req, res, next and returns promises (.then > JSON is returned, .catch > error is returned). I'll be routing the paths reqs to their corresponding api endpoints in the controllers.
This makes sense (right?) when I'm purely working on API calls where JSON is the res. However, I also want to call these api endpoints > get their res.json > and use that to render my HTML using Handlebars. What is the best way to accomplish this? I can create same controllers and instead of resp being JSON, I can do render ("html view", res.json). But that seems like I'm repeating same code again just to change what to do with the response (return JSON or Render the JSON).
Hope I'm making sense, if not, do let me know. Please advise.
p.s. try to ELI5 things for me. (:
Edit:
//Model Example
const Schema = require('mongoose').Schema;
const testSchema = new Schema({
testText: { type: String, required: true },
});
const Test = mongoose.model('Test', testSchema);
module.exports = Test;
//Controller Example
const model = require('../models');
module.exports = {
getAll: function(req, res, next) {
model.Test.find(req.query)
.then((testItems) => {
!testItems.length
? res.status(404).json({ message: 'No Test Item Found' })
: res.status(200).json(testItems);
})
.catch((err) => next(err));
},
};
//Route Example
const router = require('express').Router(),
controller = require('../controllers');
router.get('/', controller.getAll);
module.exports = router;
I want the endpoints to return JSON and somehow manage whether to render (if the req comes from a browser) or stay with JSON (if called from Postman or an API web URL for example) without repeating the code. I'm trying to not create two endpoitns with 99% of the code being the same, the only difference being .then > res.status(200).json(testItems); vs .then > res.status(200).render('testPage', { testItems}).
For postman you could check the existence of postman-token in req.headers, then you could render accordingly, something like this:
req.headers['postman-token'] ? res.json({ /* json */ }) : render('view', {/ * json */});
If you want to go with checking postman token then you can use similar to method1.
if you want to check with query params in this case you can get json response or html even from browser for future use also and is not dependent on postman then use similar to method2 of the following example.
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
const port = 5000
app.get('/method1', (req, res) => {
const isJSONResp = req.headers['postman-token']
const resp = { status: "hello" }
if (isJSONResp) {
res.json(resp)
} else {
res.render('some.html', resp)
}
})
app.get('/method2', (req, res) => {
const params = req.params
const resp = { status: "hello" }
if (params.resp === 'json') {
res.json(resp)
} else {
res.render('some.html', resp)
}
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))

How to pass data between express routes?

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,

Nodejs: Display POST data from another website

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 });
})
})

Categories

Resources