Handlebar Issues - javascript

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"
}

Related

req.body returns undefined when I use express router, even though I used express.urlencoded

Here is my server.js code:
const express = require("express");
const articleRouter = require("./routes/articles");
const app = express();
app.set("view engine", "ejs");
app.use("/articles", articleRouter);
app.use(express.urlencoded({ extended: true }));
app.get("/", (req, res) => {
const articles = [
{
title: "Test Article 1",
createdAt: new Date(),
description: "Test description 1",
},
{
title: "Test Article 2",
createdAt: new Date(),
description: "Test description 2",
},
];
res.render("articles/index", { articles: articles });
});
// app.post("/articles", (req, res) => {
// console.log(req.body);
// });
app.listen(3000, () => {
console.log("Listening on port 3000...");
});
This code (which I commented) works fine
app.post("/articles", (req, res) => {
console.log(req.body);
});
But when I try to do the same thing with router, it returns undefined. Here is my articles.js code from routes folder:
const express = require("express");
const router = express.Router();
router.get("/new", (req, res) => {
res.render("articles/new");
});
router.post("/", (req, res) => {
console.log(req.body);
});
module.exports = router;
Here id new.ejs code, where the from is:
<body>
<div class="container">
<h1 class="mb-4">New Article</h1>
<form action="/articles" method="post">
<%- include('_form_fields') %>
</form>
</div>
</body>
The problem occurs only when I try to do this in router file. I would be very thankful if anyone can tell me what exactly am I doing wrong?
You need to use any router after using middlewares.
I think using express.json() is required for parsing json from body of http request
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// ... any middleware
app.use("/articles", articleRouter);
You should pass the app to the router file and then use it regularly like this:
const articleRouter = require("./routes/articles");
articleRouter(app);
in the articleRouter file:
module.exports = (app) => {
app.post("/", (req, res) => {
console.log(req.body);
});
}

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

Unable to render JSON in html - node.js

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

Having an Issue with Multer/Express/MongoDB - File saved to DB correctly, 404 error in view

I'm having an issue that I haven't been able to figure out, despite a few hours of searching for an answer online. I'm using Node, Express, MongoDB, Multer and EJS templates and I'm attempting to save an image to the DB, and then use it in one of my views.
I was first having trouble getting the file to save to the DB correctly, but with the help of this site, I was able to work through that. But my issue now is when I try to use this in one of my views, I keep getting a weird 404 error that has a strange path:
CANNOT GET:
http://localhost:3090/project/%7B%20contentType:%20'image/png',%20%20data:%…b%2047%2044%2000%20ff%2000%20ff%2000%20ff%20a0%20bd%20a7%20...%20%3E%20%7D
404 (Not Found)
This made me think it wasn't correctly saved in the DB, but in Robomongo, it looks like this, which seems correct to me:
So, I can see that it has my content type in the URL, which is clearly a mistake, but I can't figure out how to fix this.
I have some previously added images to that file that aren't saved to the DB, and those show just fine using the same template, so the path should be correct.
Many thanks to you all in advance!!
My Index.JS file:
const express = require('express');
const http = require('http');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const mongoose = require('mongoose');
const path = require('path');
mongoose.Promise = global.Promise;
const router = require('./router');
//App Setup
const app = express();
app.set("view engine", "ejs");
app.use(express.static(path.join(__dirname, 'public')));
app.use(morgan('combined'));
app.use(bodyParser.urlencoded({extended:true}));
router(app);
//DB Setup
mongoose.connect('mongodb://localhost/projectsApp');
mongoose.connection.on('open', () => {
console.log('Connected to mongodb server.');
mongoose.connection.db.listCollections().toArray(function (err, names) {
if(err) {
console.log(err);
} else {
console.log(names);
}
});
})
//Server Setup
const port = process.env.PORT || 3090;
const server = http.createServer(app);
server.listen(port);
router.js file:
const Project = require('./models/project');
const multer = require('multer');
const fs = require('fs');
const path = require('path');
var upload = multer({ dest: './public/img' })
module.exports = function(app) {
app.get('/admin', (req, res) => {
Project.find({}, (err, projects) => {
if(err) {
console.log(err);
} else {
res.render('admin', {projects: projects});
}
})
});
app.post('/admin', upload.single('image'), (req, res) => {
console.log(req.file);
newProj = {
title: req.body.title,
tech: req.body.tech,
url: req.body.url,
shortDescription: req.body.shortDescription,
longDescription: req.body.longDescription,
image: { data: fs.readFileSync(req.file.path), contentType: 'image/png' }
};
Project.create(newProj, (err, proj) => {
if(err){
console.log(err);
} else {
console.log(proj);
res.redirect("/");
}
});
});
}
and finally, the view, just in case:
<% include ./partials/header%>
<div class="container">
<div class="row">
<div class="col-sm-6">
<div class="project-div">
<h1><%= project.title%></h1>
</div>
</div>
<div class="col-sm-6">
<img src='<%= project.image%>'/>
<hr />
<span><strong>URL: </strong> <%= project.url%></span>
</div>
</div>
</div>
<% include ./partials/footer%>
You are trying to output the object holding the image data directly in your template. This won't work because that's simply not how html work...
I would recommend setting up another route for the image, and then referring to that image.
app.get('/admin/projects/:id/image', (req, res, next) => {
Project.find({ _id: req.params.id }, (err, result) => {
if (err) return next(err)
if (result.length === 0) return next()
res.set('Content-Type', result[0].contentType)
res.send(result[0].data)
})
})
and then using that url in your template:
...
<img src="/admin/projects/<%= project._id %>/image" />
...

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