Trying to add a business in node express framework - node.js

I'm trying to add a business in Node Express Framework. My issue is that when I fill out the form to add the business, nothing adds to the page. Been trying to figure out this error for some time now.
My business.js code:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Business = require('../models/business');
var passport = require('passport');
// set up the GET handler for the main movies page
router.get('/', function(req, res, next) {
// use the Article model to retrieve all movies
Business.find(function (err, business) {
// if we have an error
if (err) {
console.log(err);
res.end(err);
}
else {
// we got data back
// show the view and pass the data to it
res.render('movies/index', {
title: 'Business',
business: business
});
}
});
});
// GET handler for add to display a blank form
router.get('/add', function(req, res, next) {
// new
if (req.isAuthenticated()) {
res.render('movies/add', {
title: 'Add a New Business'
});
}
else {
res.redirect('/auth/login');
}
});
// POST handler for add to process the form
router.post('/add', function(req, res, next) {
// save a new article using our Article model and mongoose
Business.create( {
name: req.body.name,
city: req.body.city,
province: req.body.province,
postal: req.body.postal,
street: req.body.street
}
);
// redirect to main business page
res.redirect('/business');
});
// GET handler for edit to show the populated form
router.get('/:id', function(req, res, next) {
// create an id variable to store the id from the url
var id = req.params.id;
// look up the selected article
Business.findById(id, function(err, business) {
if (err) {
console.log(err);
res.end(err);
}
else {
// show the edit view
res.render('movies/edit', {
title: 'Business Details',
business: business
});
}
});
});
// POST handler for edit to update the article
router.post('/:id', function(req, res, next) {
// create an id variable to store the id from the url
var id = req.params.id;
// fill the article object
var business = new Business( {
_id: id,
title: req.body.title,
content: req.body.content,
date: req.body.date,
rating: req.body.rating,
actor: req.body.actor
});
// use mongoose and our Article model to update
Business.update( { _id: id }, business, function(err) {
if (err) {
console.log(err)
res.end(err);
}
else {
res.redirect('/business');
}
});
});
//get handler for delete using the article id
router.get('/delete/:id', function(req, res, next){
//grab the id parameter from the url
var id = req.params.id;
Business.remove({ _id: id }, function(err) {
if(err) {
console.log(err);
res.end(err);
}
else {
// show updated business page with redirect
res.redirect('/business');
}
});
});
////auth check
//function isLoggedIn(req, res, next) {
// //is the user authenticated>
// if (req.isAuthenticated()) {
// return next();
// }
// else {
// res.redirect('/auth/login');
// }
//}
// make public
module.exports = router;
My add.ejs code:
<%- include ../partials/header.ejs %>
<main>
<form method="post" action="add">
<fieldset>
<label for="name">Name:*</label>
<input type="text" name="name" required />
</fieldset>
<fieldset>
<label for="city">City:*</label>
<input type="text" name="city" required>
</fieldset>
<fieldset>
<p>
<label>Province:*</label>
<select id="province" required>
<option value="--">--</option>
<option value = "ontario">ON</option>
<option value = "quebec">QC</option>
<option value = "british columbia">BC</option>
<option value = "alberta">AL</option>
<option value="nova scotia">NS</option>
<option value="manitoba">MB</option>
<option value="newfoundland">NL</option>
<option value="pei">PEI</option>
</select>
</p>
</fieldset>
<fieldset>
<label for="postal">Postal Code:*</label>
<input type="text" name="postal" required>
</fieldset>
<fieldset>
<label for="street">Street Name:*</label>
<input type="text" name="street" required>
</fieldset>
<button class="btn btn-primary" type="submit">Save</button>
</form>
</main>
</body>
</html>
Thanks so much in advance!

Related

Can't update model with mongoose schema

i'm trying to make an update functionality but it doesn't update the model :( First i make a get request to get the data from the server and populate it in form(handlebars)
so, here's the router:
router.get('/edit/:id', async (req, res) => {
const warum = await Warum.findById(req.params.id)
res.render('edit', warum);
});
router.post('/edit/:id', (req, res) => {
return Warum.findOneAndUpdate(req.params.id, { new: true }, {
title: req.body.title,
description: req.body.description,
})
.then(() => {
res.redirect('/warum');
})
.catch((err) => {
console.log(err);
});
});
that's the form:
<form method="post">
<h2>Beitrag bearbeiten</h2>
<ul class="noBullet">
<li>
<label for="title">Titel:</label>
<input type="text" name="title" value="{{title}}" />
</li>
<li>
<label for="description">Beschreibung:</label>
<textarea class="texterea" name="description">
{{description}}
</textarea>
</li>
<div>
<button class="login-button">save</button>
</div>
</ul>
</form>
and that's the schema:
const mongoose = require('mongoose')
const WarumSchema = new mongoose.Schema({
title: String,
description: String,
});
const Warum = mongoose.model('Warumschema', WarumSchema);
module.exports = Warum;
I tried to change the route from post to put, but then it says 404. After clicking the save button it just redirects me, but the result is not edited.

Automatic redirection to "/undefined" in express (nodejs)

I have been working on a code for a to do list, The issue comes when I actually go to a custom list domain and use the delete method, after deleting the method, the website automatically redirects to "localhost:3000/undefined" and the website fails to respond further, all the functionality stops except the display of the existing elements
This is the node js file
const express=require("express");
const bodyParser=require("body-parser");
const ejs = require('ejs');
const mongoose=require("mongoose")
const app=express();
app.use(bodyParser.urlencoded({extended:true}))
app.set('view engine', 'ejs')
app.use(express.static("public"));
mongoose.connect("mongodb://localhost:27017/todolsDB");
const itemsSchema=new mongoose.Schema({
toDoToday: String
});
const Item=mongoose.model("Item", itemsSchema);
const itemOne=new Item({
toDoToday: "Wake Up"
});
const itemTwo=new Item({
toDoToday: "Get up"
});
const itemThree=new Item({
toDoToday: "Stand up"
});
const Items=[itemOne,itemTwo, itemThree];
const listSchema = {
name: String,
items: [itemsSchema]
};
const List = mongoose.model("List", listSchema);
app.get("/", function(req, res){
Item.find({}, function(err, Items){
if (Items.length===0){
Item.insertMany(Items, function(err){
if(err){
console.log(err)
}
else{
console.log("Succesfully added!")
}
})
res.redirect("/")
}
else{
res.render("lists .ejs", {Day: "Today", newListItem: Items});
}
})});
app.get("/:topic", function(req, res){
const topic=req.params.topic;
List.findOne({name: topic}, function(err, results){
if (!err){
if (!results){
const list = new List({
name: topic,
items: Items
});
list.save();
res.redirect("/" + topic);
}
else{
res.render("lists .ejs", {Day: results.name, newListItem: results.items});
}
}
});
})
app.post("/",function(request, response){
var itemName=request.body.newElement;
const listName=request.body.list
const item=new Item({
toDoToday: itemName
});
if (listName==="Today"){
response.redirect("/");
item.save();
}else{
List.findOne({name:listName}, function(err, results){
console.log(results)
results.items.push(item)
results.save()
response.redirect("/"+listName);
})
}
})
=
app.post("/delete", function(req, res){
const checkedItemId = req.body.checkbox;
const listName = req.body.listName;
if (listName === "Today") {
Item.findByIdAndRemove(checkedItemId, function(err){
if (!err) {
console.log("Successfully deleted checked item.");
res.redirect("/");
}
});
} else {
List.findOneAndUpdate({name: listName}, {$pull: {items: {_id: checkedItemId}}}, function(err, foundList){
if (!err){
res.redirect("/" + listName);
}
});
}
});
app.listen(3000, function(){
console.log("connected to port 3000");
})
Here is the "list .ejs" file
<%-include('header.ejs')%>
<body>
<div class="box" id="heading">
<h1>Today is <%= Day %></h1>
</div>
<div class="box">
<% newListItem.forEach(function(item){ %>
<form action="/delete", method="POST">
<div class="item">
<input type="checkbox" name="checkbox" value="<%=item._id%>" onchange="this.form.submit()">
<p><%= item.toDoToday %> </p>
</form>
</div>
<% }) %>
<div>
<form action="/" method="POST" class="item">
<button type="submit" name="list" value=<%= Day %> >+</button>
<input type="text" name="newElement" placeholder="New Element" autocomplete="off">
<input type="hidden" name="listName" id="" value=<%= Day %> > </input>
</div>
</div>
<%-include('footer.ejs')%>
</form>
<script src="" async defer></script>
</body>
</html>
On this route you have req.body.list
app.post("/",function(request, response){
var itemName=request.body.newElement;
const listName=request.body.list
const item=new Item({
toDoToday: itemName
});
And on this route you have req.body.listName
app.post("/delete", function(req, res){
const checkedItemId = req.body.checkbox;
const listName = req.body.listName;
Most likely you are trying to access an object which does not exist, so change the property name.

Cant Save to MongoDB database and using handlebars

this is my post request to save to mongdb database
router.post("/create", async (req, res) => {
const createJottings = new Jottings({
title: req.body.title,
jottings: req.body.jottings
});
try {
await createJottings.save();
res.json(createJottings);
} catch (err) {
res.json({ message: err });
}
});
it works fine on postman but now i am trying to render it using handlebars to the client. this is the form for the client side using handlebars
<div class="card card-body">
<h3>
Edit Jottings/Idea
</h3>
<form action="/jottings/create" method="get">
<div class="form-group">
<label for="title">
Title
</label>
<input type="text" name="title" class="form-control" required />
</div>
<div class="form-group">
<label for="title">
Jottings
</label>
<textarea name="Description" class="form-control" required></textarea>
</div>
<button type="submit" class="btn btn-primary">
Submit
</button>
</form>
</div>
the form actually loads but when i press submit it doesnt save to mongodb server
{{#each getJottings}}
<div class="card card-body mb-2">
<h4>
{{title}}
</h4>
<p>
{{jottings}}
</p>
<a href="/jottings/edit/{{id}}" class="btn btn-dark btn-block">
Edit
</a>
</div>
{{else}}
<p>
No Ideas and Jottings listed
</p>
{{/each}}
code that outlists saved data in the database if i create it using postman it works but with the form it doesnt.
overview of my jottings route
// Require Mongoose
const router = require("express").Router();
// Setup Models for Jotting
const Jottings = require("../models/jottings.model");
// Setting Endpoints For Routes
// Get All Jottings
router.get("/", async (req, res) => {
try {
const getJottings = await Jottings.find({}).sort({ date: "desc" });
res.render("jottings/index", {
getJottings: getJottings
});
} catch (err) {
res.json({ message: err });
}
});
// Getting routes to set form
router.get("/add", (req, res) => {
res.render("jottings/add");
});
// Get Specific Jottings
router.get("/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
await Jottings.findById(id, (err, jottings) => {
if (!id) {
res.json({ message: err });
} else {
res.json(jottings);
}
});
} catch (err) {
res.json({ message: err });
}
});
// Post to create New Jottings for form
router.post("/create", async (req, res) => {
const createJottings = new Jottings({
title: req.body.title,
jottings: req.body.jottings
});
try {
await createJottings.save();
res.json(createJottings);
} catch (err) {
res.json({ message: err });
}
});
router.get("/edit/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
const editJottings = await Jottings.findOne({ _id: id });
res.render("jottings/edit", {
editJottings: editJottings
});
} catch (err) {
res.json({ message: err });
}
});
// Patch to Edit Jottings for form
router.patch("/edit/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
const editJottings = await Jottings.updateOne(
{ _id: id },
{ $set: { jottings: req.body.jottings } }
);
res.render("jottings/edit", {
editJottings: editJottings
});
} catch (err) {
res.json({ message: err });
}
});
// Delete to delete Jottings for form
router.delete("/delete/:id", async (req, res) => {
try {
// Requesting for request paremeter given to ever document created in mongoDB
const id = req.params.id;
const deleteJottings = await Jottings.deleteOne({ _id: id });
res.json(deleteJottings);
} catch (err) {
res.json({ message: err });
}
});
// Exporting router
module.exports = router;
i would like the details to be saved to the database when i click the submit button and also redirect me to a list of my saved details.
You form uses method GET while you defined router.post to handle form submission.

fetch POST returns only _id object in Express API server React FrontEnd

I'm trying to make a React-Node.js application for practice. I encountered an problem in sending POST request. When I fetch POST request in App.js, it returns only id. I expected it to return 3 more values.
Current object
{ _id: 5a046d52bb5d37063b3c8b21 }
Ideal object
{_id: "59e9fed60fe8bf0d7fd4ac6e", name: "recipe1", ingredients: "apple", descriptions: "cut an apple"}
How should I add values to req.body correctly? I referred this solution Post an object with fetch using react js and express API server but it didn't work with my app.
index.js (node.js)
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();
// Serve static files from the React app
app.use(express.static(path.join(__dirname, 'client/build')));
app.use(bodyParser.urlencoded({ extended: true}));
var db
const MongoClient = require('mongodb').MongoClient
MongoClient.connect
('mongodb://Recipe:recipebox#ds125914.mlab.com:25914/ayumi', (err, database) => {
if (err) return console.log(err)
db = database
app.listen(8080, () => {
console.log('listening on 8080')
})
})
app.get('/api', (req,res)=> {
db.collection('recipe').find().toArray((err, results) => {
if(err) return console.log("no recipe");
res.json(results);
})
})
app.post('/recipe', (req,res)=>{
db.collection('recipe').save(req.body, (err, result) => {
if(err) return console.log(err);
console.log(req.body)
console.log('save to database');
res.redirect('/');
})
})
App.js (react)
class App extends Component {
constructor(props){
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e){
e.preventDefault();
fetch('/recipe', {
method: 'POST',
body: JSON.stringify({
name: this.refs.name.value,
ingredients: this.refs.ingredients.value,
descriptions: this.refs.descriptions.value
}),
headers: {"Content-Type" : "application/json"}
})
.then((res)=> {
return res.json()
})
.then((body)=>{
console.log("body" + body)
console.log("result" + this.refs.name.value)
})
}
render() {
return (
<div className="App">
<h1>Recipe List</h1>
<form onSubmit={this.handleSubmit}>
<input type="text" placeholder="name" ref="name" />
<input type="text" placeholder="ingredients" ref="ingredients" />
<input type="text" placeholder="descriptions" ref="descriptions" />
<input type="submit"/>
</form>
</div>
)
}
}
export default App;
Server-side changes:
app.post('/recipe', (req, res) => {
// log the body of the request, to make sure data is properly passed
console.log(req.body);
// use mongodb's insertOne instead of the deprecated save
db.collection('recipe').insertOne(req.body, (err, result) => {
if (err) return console.log(err);
// log the result of db insertion
console.log(result);
console.log('saved to database');
// send the freshly saved record back to the front-end
res.json(result);
});
});
Front-end changes:
class App extends Component {
constructor(props){
super(props);
// add state to hold recipe returned from POST call
this.state = {
recipe: null,
name: '',
ingredients: '',
descriptions: ''
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const { name, ingredients, descriptions } = this.state;
fetch('/recipe', {
method: 'POST',
body: JSON.stringify({
name,
ingredients,
descriptions
}),
headers: {"Content-Type" : "application/json"}
})
// when call completes, it should return the newly created recipe object
// as it was saved in the DB - just store it into state
.then((recipe)=> {
this.setState({recipe});
});
// TODO: handle error case
}
render() {
// added a paragraph tag to display the ID of the freshly created recipe
// it's only displayed if recipe is not null or undefined
// further changes: turning inputs into controlled inputs
const { name, ingredients, descriptions } = this.state;
return (
<div className="App">
<h1>Recipe List</h1>
<form onSubmit={this.handleSubmit}>
<input
value={name}
type="text"
onChange={e => this.setState({ name: e.target.value })}
placeholder="name" />
<input
value={ingredients}
type="text"
onChange={e => this.setState({ ingredients: e.target.value })}
placeholder="ingredients" />
<input
value={descriptions}
type="text"
onChange={e => this.setState({ descriptions: e.target.value })}
placeholder="descriptions" />
<input type="submit"/>
{ recipe &&
<p>Saved ID: {this.state.recipe._id}</p>
}
</form>
</div>
);
}
}
export default App;
Further changes: turned all three text inputs into controlled inputs (values of all 3 fields are tracked in state, and passed to fetch when the form is submitted).

bcrypt.compareSync is always returning false

I verified that in my db I am saving the username and hash of the password. I am able to retrieve the name from the db, however when I check the password it always returns false. Not sure what is wrong.
Here is my HTML
<div ng-controller="userController">
<div class=user>
<form name="login_form">
<h2 class>Login</h2>
<h3 class = "login_page">UserName</h3>
<input ng-model="user" type="text" ng-minlength="1" required>
<h3 class = "login_page">Password</h3>
<input ng-model="password" type="password" name="password" ng-minlength="4" required>
<input type="submit" value="Login" ng-click="login()" >
<div ng-if ="login_form.$submitted" ng-messages="login_form.password.$error" style="color:maroon" role="alert">
<div ng-message="minlength">Your field is too short</div>
</div>
<p ng-if="error">Username or login is incorrect</p>
</form>
</div>
<div class=user>
<form name = "register_form">
<h2 class>Register</h2>
<h3 class = "login_page">UserName</h3>
<input ng-model="reg.name" type="text" required>
<h3 class = "login_page">Password</h3>
<input ng-model="reg.password" type="password">
<input type="submit" value="Register" ng-click="register()" required >
<div ng-if ="login_form.$submitted" ng-messages="login_form.password.$error" style="color:maroon" role="alert">
<div ng-message="minlength">Your field is too short</div>
</div>
<p ng-if="duplicate">That user name is taken, please choose another</p>
<p ng-if="correct">Registration Succesfull</p>
</form>
</div>
</div>
Here is my controller on the server side
var mongoose = require('mongoose'),
Todo = mongoose.model('Todo');
Login = mongoose.model('Login');
var bcrypt = require('bcrypt');
var name = ""
module.exports = (function(){
return {
save_name:function(req, res){
req.session.user = req.body.user
Login.findOne({name: req.body.user},
function(err, user) {
if(user){
console.log(user.password);
console.log( bcrypt.compareSync(req.body.password, user.password));
res.json({'error': false});
}else {
res.json({'error': true});
}
})
}, //end of save name method
register:function(req, res){
bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(8));
login = new Login({
name:req.body.user,
password: bcrypt.genSaltSync(8)
})
login.save(function(err){
if(err){
res.json({'error': true});
} else {
res.json({'sucess': true})
}
})
} // end of register user function
}
})();
You're saving a generated salt as the password instead of the actual hash itself. Also, explicitly calling genSalt*() is unnecessary. Lastly, you really should use the async functions instead, to avoid unnecessarily blocking the event loop. So with all of this in mind, you may end up with something like:
module.exports = {
save_name: function(req, res) {
req.session.user = req.body.user;
Login.findOne({ name: req.body.user },
function(err, user) {
if (err)
return res.json({ error: true });
bcrypt.compare(req.body.password,
user.password,
function(err, valid) {
res.json({ error: !!(err || !valid) });
});
});
}, // end of save name method
register: function(req, res) {
bcrypt.hash(req.body.password, 8, function(err, hash) {
if (err)
return res.json({ error: true });
login = new Login({
name: req.body.user,
password: hash
})
login.save(function(err) {
res.json({ error: !!err });
})
});
} // end of register user function
};
Despite other answers, if it is still not resolving your issue. Try by applying the toString() when passing the password upon login like this.
req.body.password.toString();
The immediate cause of your bug is in register you should be using bcrypt.hashSync(myPlaintextPassword, saltRounds) instead of genSaltSync. Fixing that should make things "work".
However, you need to recode all this to use the async bcrypt APIs or your application will respond very poorly under load (like crippled and unusable, not just "slow"). General rule: no sync calls in a node.js server.

Resources