Unable to render JSON in html - node.js - javascript

This is probably a simple solution, however I cannot figure out how to carry my JSON object over to my view. Normally you'd throw JSON into res.render() inside your app.get .. unfortunately I am having trouble. A problem arises because i need to be able to send form data from html to my API request, then grab that JSON object and display it in my view. I can see it in my console, but unable to carry it over to html. Would love some help or guidance on how to improve my code or find a solution. Any help is appreciated! - View code below:
Server.js
var path = require('path');
var express = require('express');
var exphbs = require('express-handlebars');
var bodyParser = require('body-parser');
var Bls2 = require('bls2');
var app = express();
app.engine('html', exphbs({ extname: '.html' }));
app.set('view engine', 'html');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var blsRequest = function(req, res, inputContent){
const API_KEY = //bls API key here
let bls = new Bls2(API_KEY);
console.log('this is seriesID =', inputContent);
let options = {
'seriesid': [inputContent],
'startyear': '2008',
'endyear': '2018',
// ...
};
bls.fetch(options).then(function (response) {
var data = JSON.stringify(response)
console.log(data);
console.log('API Call Complete')
res.send({data : data}); //need to render home view and JSON HERE
});
}
app.get('/', function (req, res) {
res.render('home');
});
app.post('/', function(req, res){
let inputContent = req.body.seriesID;
blsRequest(req, res, inputContent);
});
app.listen(8000);
html
<!DOCTYPE html>
<html>
<head>
<title>LBS</title>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="crossorigin="anonymous"></script>
</head>
<body>
<div class="container-fluid">
<form id="seriesID">
<div class="form-group" method="post" action='/'>
<label for="seriesID">Input Series ID</label>
<input type="text" class="form-control" name="seriesID" placeholder="Series ID">
</div>
<button class="btn btn-primary" type="submit" >Search</button>
</form><br>
uhh JSON should be here: {{data}}
</div>
</body>
<script type="text/javascript">
$("#seriesID").submit(function (event) {
$.post('/', $("#seriesID").serialize(), function (data) {
//data is the response from the backend
});
event.preventDefault();
});
</script>
</html>

use res.render('home',{data});
because your{{data}} is undefined that's why it is not printing anything
it is even better to use {{JSON.stringify(data)}}

Related

Why am I getting a Cannot POST /api/ error when trying to post to a form?

I have a basic website and am running into a problem. I am extremely new to this and can not seem to fix it.
When I run the server and browse to http://localhost:3000/class/create everything works fine. However, when I try to add a student I receive a message on the browser that says
" Cannot POST /api/create " and a 404 error in the console.
What is supposed to happen: The console logs "creating a student entry"
index.js
const express = require('express')
const app = express()
// loading body-parser
const bodyParser = require('body-parser')
// loading our routers
const mainRouter = require('./mainRoutes.js')
const classRouter = require('./classRoutes.js')
// tell Express to use bodyParser for JSON and URL encoded form bodies
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
// mounting the routers
app.use('/', mainRouter)
app.use('/class', classRouter)
app.listen(3000)
console.log('Express server running on port 3000')
classRoutes.js
const path = require('path')
const express = require('express')
const router = express.Router()
const classList = [] // our class list array
router.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'views', 'class', 'index.html'))
})
router.get('/create', function (req, res) {
res.sendFile(path.join(__dirname, 'views', 'class', 'create.html'))
})
// RESTful api
router.get('/api/list', function (req, res) {
res.json(classList) // Respond with JSON
})
router.get('/api/get/:id', function (req, res) {
res.json(classList[req.params.id]) // Notice the wildcard in the URL?
// Try browsing to /api/get/0 once you've added some entries
})
router.post('/api/create', function (req, res) {
console.log('creating a student entry')
})
module.exports = router
create.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Class List: Create</title>
<meta charset="utf-8" />
</head>
<body>
<form action="/api/create" method="post">
<div>
<label for="studentName">Enter The Student's Name:</label>
<input type="text" id="student" name="student">
</div>
<div class="button">
<button type="submit">Add</button>
</div>
</form>
</body>
</html>
Chrome Dev Tools output (network tab)
because you set app.use('/class', classRouter); /class must precede /api/create so the correct route is/class/api/create
use the correct absolute path: action="/class/api/create"

Handlebar Issues

I am currently trying to run a GET operation but my code doesn't seem to work. I already have the simple set up done but when I click the button I created to request the data from a simple .JSON file I made I keep getting "0 documents retrieved". Could anyone assist with this? here is my code attached in screenshots. Any and all help is appreciated. Thank you.
Handlebars -
<!DOCTYPE html>
<html>
<head>
<title>Get Request</title>
</head>
<body>
<h2>GET Request</h2S>
<div class="results">
{{#each data}}
<p> {{first_name}} {{last_name}} </p>
{{/each}}
</div>
</body>
</html>
HTML -
<h2>GET Request</h2>
<p>
<a href="/api/user"
data-selector="results">Load user data</a>
<form action="/api/user" method="GET"></form>
</p>
<div class="results"></div>
JavaScript -
const express = require("express")
const app = express();
const mongo = require('mongodb').MongoClient;
const assert = require('assert');
const url = 'mongodb://localhost:27017/test';
var bodyParser = require('body-parser');
var exphbs = require('express-handlebars');
app.set('view engine', 'handlebars');
app.engine('handlebars', exphbs());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.get('/api/user', function(req, res) {
mongo.connect(url,{ useUnifiedTopology: true }, function(err, database) {
const db = database.db('test');
db.collection('users').find()
.toArray(function(err, result) {
if (err) {
throw err;
}
console.log(result.length + ' documents retrieved.');
//res.json(result);
res.render('user', { data:result, layout:false})
database.close();
});
});
});
app.get('*', function (request, response) {
response.sendFile('./public/hello.html',{root: __dirname});
});
const port = 8900;
app.listen(port);
console.log(`Listening to server: http://localhost:${port}`)
JSON -
{
"id": 1,
"name": {
"first_name": "Robert",
"last_name": "Swanson"
},
"title": "Some Dude"
}

Redirect to another url after post request (AJAX, EXPRESS)

As a part of learning node.js servers I'm working on a little log-in website. There's a site you can open and enter your username which will then be sent through an ajax post request to the server and saved into an array of all users. I wanna make it so that after you submit your username, you will be redirected to another page, unique for every username, where you will be able to see the information about you username. Sort of a 'manage your account' site.
However, I can't seem to figure out a way to redirect me to this page after I have submitted an username.
Say for example you submit a username 'kokot' and it's the 3rd username that's been submitted so far. Thus, in the 'players' array, your user object will look something like this {id: 2, username: 'kokot'}.
Now I want to redirect you to the url localhost:2000/players/2 to see the info about your specific username.
NODE JS
const express = require('express');
const server = express();
const bodyParser = require('body-parser');
server.use(bodyParser.urlencoded({extended: false}));
server.use(bodyParser.json());
let players = [];
//loads the home page
server.get('/', (req, res) =>{
res.sendFile(__dirname + '/home.html');
});
//loads the page with the list of players
server.get('/players', (req, res) =>{
res.send(players);
});
server.get('/player/:id', (req, res) =>{
res.send(players[req.params.id]);
});
//takes a new username and saves it to players array
server.post('/', (req, res) =>{
console.log('NEW PLAYER: ' + req.body.username);
players.push({
id: players.length,
username: req.body.username
});
});
/////////////////////////////////////////////////////////////////////////////
server.listen(2000, () => console.log('LISTENING ON PORT 2000'));
HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<title>Home</title>
</head>
<body>
<h1>PISKVOREC</h1>
<form id="userForm">
username
<input type="text" name="text" id="userFormInput">
<input type="submit" name="Submit" id="userFormSubmit">
</form>
<script>
$(document).ready(()=>{
let homeUrl = 'http://localhost:2000';
let $userForm = $('#userForm');
let $userFormSubmit = $('#userFormSubmit');
//submits a new username to the server
$userFormSubmit.click(() =>{
$.post(homeUrl, {
username: $('#userFormInput').val()
}, function(){
console.log('USERNAME SUBMITTED TO SERVER');
});
$.
});
////////////////////
});
</script>
</body>
</html>
Thank you for you responses and ideas
Have a nice day
Sure, see below:
server.post('/', (req, res) =>{
console.log('NEW PLAYER: ' + req.body.username);
players.push({
id: players.length,
username: req.body.username
});
res.redirect(`/player/${req.body.username}`);
});
UPDATE
Demo with vanilla Express.js app
app.js
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
app.post('/this', (req, res, next) => {
res.redirect(`/that/${req.body.username}`);
});
app.get('/that/:id', (req, res, next) => {
res.send(req.params);
});
module.exports = app;
index.hbs
<form method="post" action="/this">
<input id="username" name="username" value="vader" type="text" />
<button type="submit">Submit</button>
</form>
results in a redirect to: http://localhost:3000/that/vader

Node js : Using Handlebars and Bodyparser together

In this basic program I would like to get user input using 'body parser' and then enter that input via handlebars onto the index page. I have attempted many times but can't seem to acheive it. Also does handlebars and bodyparser go together or should I be using something different.
Template:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<header>
<h1>Bodyparser and Handlebars</h1>
</header>
<form method="post" action="/">
<input type="text" name="name1">
<input type="submit" value="Submit">
</form>
{{test}}
</body>
</html>
Node.js
var express = require('express');
var app = express();
var handlebars = require('express-handlebars');
var path = require("path");
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.set('view engine', 'html');
app.engine('html', handlebars({
defaultLayout: 'base',
extname: '.html'
}));
app.use(express.static(path.join(__dirname, 'public'))); //public directory
app.get('/index', function(req, res) {
res.sendFile('index.html', { root: __dirname });
});
app.get('/', function (req, res) {
res.render('index', {
test: req.body.name1});
});
app.post('/', function(req, res){
console.log(req.body.name1);
});
app.listen(3000);
Your post to / should be:
app.post('/', function(req, res){
res.render('index', {
test: req.body.name1});
});
And you are done.
Body-parser and handlebars work perfect togheter. Body-parser allows you to collect the request data inside the router controller and handlebars is a template engine that render the variables and more stuff.
You need to pass the text that you want to display to the POST router controller.
<form action="/" method="post">
name1: <input type="text" name="name1"><br>
<input type="submit" value="Submit">
</form>
Put that form in other view or anywhere you want
Inside the controller pass the request parameter to handlebars:
app.post('/', function(req, res){
res.render('index', {
test: req.body.name1});
});

Unable to Manipulate DOM with cheerio on nodejs

I'm running a simple program with the server side on Node with cheerio. Given below are the codes:
Server Side:
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, request = require ('request')
, cheerio = require ('cheerio')
, $;
var app = express();
//console.log($('[class = "orange"]').attr('id'));
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
request('http://localhost:3000', function (error, response, html) {
if (!error && response.statusCode == 200) {
$ = cheerio.load(html);
}
});
app.listen(3000);
var temp2=9;
app.get('/data2', function(req, res){
//var $ = cheerio.load('<body>');
//var temp = $('[class="orange"]').attr('id');
console.log(temp2);
res.send(temp2); //replace with your data here
});
app.get('/data', function(req, res){
//var $ = cheerio.load('<body>');
var temp = $('[class="orange"]').attr('id');
console.log(temp);
res.send(temp); //replace with your data here
});
index.ejs (Express Template)
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js" type="text/javascript"></script>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<input type="button" id="stopButton" value="Button1"/>
<input type="button" id="stopButton2" value="Button2"/>
<p>Welcome to <%= title %></p>
<ul id="fruits">
<li id= "1" class="apple">Apple</li>
<li id = "2" class="orange">Orange</li>
<li id = "3" class="pear">Pear</li>
</ul>
<script type="text/javascript">
$(document).ready(function () {
$('#stopButton').click(function () {
$.get('http://localhost:3000/data', {}, function (data) {
$('[id="2"]').html(data);
});
});
$('#stopButton2').click(function () {
$.get('http://localhost:3000/data2', {}, function (data2) {
console.log(data2);
$('[id="2"]').text(data2);
});
});
});
</script>
</body>
</html>
The template creates a list of items and displays it on the HTML.
Apple
Orange
Pear
Also displayed on the HTML are 2 buttons: Button1 and Button2.
When I press Button1, 'Orange' changes to number 2.
When I press Button2, ideally Orange should change to number 9, but it doesn't. Is there something wrong?
The console.log() for both buttons work perfectly well numbers 2 and 9 shown in the console.
Any help would be appreciated.
There are some misunderstandings here. This code
request('http://localhost:3000', function (error, response, html) {
if (!error && response.statusCode == 200) {
$ = cheerio.load(html);
}
});
app.listen(3000);
doesn't make sense--you're making a request to your own server in order to create the $ object to use Cheerio to parse the form. Then, when a request comes through, you try to pull the user's form data from that HTML that you parsed long ago when the server started using var temp = $('[class="orange"]').attr('id');.
Cheerio isn't able to dynamically track all of the served HTML form values on various clients, so it'll never have any of the dynamic data you may expect it to have, just the same raw HTML you're serving to the client.
Cheerio isn't useful here at all as far as I can tell. It's primarily a web scraping tool for extracting data from other websites' HTML. Data submitted by your clients to the server is taken from the payload, parameters and query string of an HTTP request using request.body, request.params and request.query. POST body payloads are commonly JSON or URL-encoded form data.
Here's a simple example of how you can send data to the server using a GET request's query string and respond with a value that the client can insert into the document. You can adapt this to your use case.
views/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= title %></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
</head>
<body>
<h1><%= title %></h1>
<input type="button" id="stop-button" value="Button1" />
<p>Welcome to <%= title %></p>
<ul id="fruits">
<li id="1" class="apple">Apple</li>
<li id="2" class="orange">Orange</li>
<li id="3" class="pear">Pear</li>
</ul>
<script>
$(document).ready(() => {
$("#stop-button").click(() => {
const url = "http://localhost:3000/data";
const word = $("#1").text();
$.get(url, {word}, ({data}) => $("#2").html(data));
});
});
</script>
</body>
</html>
server.js:
const express = require("express");
const path = require("path");
const app = express();
app.set("port", process.env.PORT || 3000);
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
app.use(express.static(path.join(__dirname, "public")));
app.get("/", (req, res) => res.render("index.ejs", {title: "foo"}));
app.get("/data", (req, res) => {
res.json({data: (req.query.word || "") + Math.random()});
});
app.listen(
app.get("port"),
() => console.log(`running on port ${app.get("port")}`)
);

Categories