I'm attempting to build my first REST API using MongoDB and Node.
I'm using Postman to test the API.
all of the methods appear to be working, but I currently cannot update any "articles" in my database, using the post method.
I'm essentially trying to edit the "title" and "content" of the articles, but Postman is returning ("update not successful").
//jshint esversion:6
const express = require("express"); //creating four constant, and requiring the modules
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require('mongoose');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ //parse requests
extended: true
}));
app.use(express.static("public")); //public directory to store static files
mongoose.connect("mongodb://localhost:27017/wikiDB", { useNewUrlParser: true }); // connect to local database
const articleSchema = { //created article schema
title: String,
content: String
};
const Article = mongoose.model("Article", articleSchema); //created article model
//Requests Targetting all Articles
app.route("/articles")
.get(function (req, res) {
Article.find(function (err, foundArticles) { //search through articles and send to client
if (!err) {
res.send(foundArticles);
} else {
res.send(err);
}
});
})
.post(function (req, res) {
console.log(req.body.title);
console.log(req.body.content);
const newArticle = new Article({
title: (req.body.title),
content: (req.body.content)
});
newArticle.save(function (err) {
if (!err) {
res.send("Successfully added a new article");
} else {
res.send(err);
}
});
})
.delete(function (req, res) {
Article.deleteMany(function (err) {
if (!err) {
res.send("Succesfully deleted all articles.");
} else {
res.send(err);
}
});
});
///request targeting a specific article/////////////////
app.route("/articles/:articleTitle") // match request parameters
.get(function (req, res) {
Article.findOne({ title: req.params.articleTitle },
function (err, foundArticle) {
if (foundArticle) {
res.send(foundArticle);
} else {
res.send("No articles matching that title was found");
}
});
})
.put(function (req, res) {
Article.updateMany(
{ title: req.params.articleTitle },
{ title: req.body.title, content: req.body.content },
{ overwrite: true },
function (err) {
if (!err) {
console.log("success")
res.send("successfully updated article")
} else {
res.send("update not successful");
console.log("error")
}
}
);
});
app.listen(3000, function () {
console.log("Server started on port 3000"); //listen on port
});
Add app.use(bodyParser()); to your code, like this:
app.use(bodyParser());
app.use(bodyParser.urlencoded({extended: true}));
You are supposed to use the update method instead of the updateMany method, as you are updating a single entry in the database.
For information: The body parser you are using is deprecated. If you are using Express >= 4.16.0, then you can use this: express.json() and express.urlencoded() by replacing your body parser code with this:
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
Hope everything works now.
Related
I am using express js, and mongoose for fetching data from collection and store it in a list and then send it to an ejs file. But I don't know why the data is not getting stored in list. below are my code.
app.get("/", (req, res) => {
let item = [];
General.find(null, (err, data)=>{
if(err){
console.log(err);
} else {
data.forEach(element => {
item.push(element.name);
});
console.log("pushed "+item);
}
});
console.log("final "+item);
res.render("index", { title: "Welcome", list: item});
});
this is what printed in console when I run the above program.
listening 3000
final
pushed item-1,item-2
Here is my DB Collection
[
{ _id: ObjectId("63d165717d847e937728e63b"), name: 'item-1', __v: 0 },
{ _id: ObjectId("63d165857d847e937728e63e"), name: 'item-2', __v: 0 }
]
Here are my configurations
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
mongoose.set("strictQuery", false);
mongoose.connect("mongodb://127.0.0.1:27017/todolistDB", { useNewUrlParser: true });
const genSchema = new mongoose.Schema({ name : String });
const General = mongoose.model("General", genSchema);
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: "true" }));
app.use(express.static("public"));
I don't understand why is my final item list is empty.
You have to wait for General.find because find method returns a Promise. Also check your logs, pushed is printed after final that shows you that your find method is an async function.
app.get("/", async (req, res) => {
let item = [];
await General.find(null, (err, data)=>{
if(err){
console.log(err);
} else {
data.forEach(element => {
item.push(element.name);
});
console.log("pushed "+item);
}
});
console.log("final "+item);
res.render("index", { title: "Welcome", list: item});
});
I am working on an educational project from udemy, by dr. yu. I am trying to add content via post request. I keep getting undefined.
From what I can tell, most solutions are user error based with post request and make sure postman form encoded option is checked, or not using body-parser. Both of those seem to be okay on my end.
The code successfully adds content, just, it's empty. Any tips?
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const _ = require("lodash");
const app = express();
app.set("view engine", "ejs");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
mongoose.connect("mongodb://localhost:27017/wikiDB", { useNewUrlParser: true });
const articleSchema = {
title: String,
content: String,
};
const Article = mongoose.model("Article", articleSchema);
app.get("/articles", function (req, res) {
Article.find(function (err, foundArticles) {
if (!err) {
res.send(foundArticles);
} else {
res.send(err);
}
});
});
app.post("/articles", function (req, res) {
const newArticle = new Article({
title: req.body.title,
content: req.body.content,
});
newArticle.save(function (err) {
if (!err) {
res.send("Successfully added a new article.");
} else {
res.send(err);
}
});
});
let port = process.env.PORT;
if (port == null || port == "") {
port = 3000;
}
app.listen(port, function () {
console.log(`Server started on port ${port} successfully`);
});
I am trying to link (href) my hbs page to a ejs page in my views folder. I have installed consolidate as seen in other tutorials via going to the directory npm install consolidate and have added the code var engines = require('consolidate'); and app.engine('handlebars', engines.handlebars); to my code but nothing works (I also know if you’re using “.ejs” extensions you don’t need to do anything). Can someone please help me out as I cannot view my pages due to this. I receive this error - "Failed to lookup view employee/addOrEdit in views directory...". I have added my folder/file structure below and code snippets. Thank you!
folder/file structure
server.js file
require('./models/db');
const express = require('express');
const path = require('path');
const exphbs = require('express-handlebars');
const bodyparser = require('body-parser');
var engines = require('consolidate');
const employeeController = require('./controllers/employeeController');
var app = express();
app.engine('handlebars', engines.handlebars);
app.use(bodyparser.urlencoded({
extended: true
}));
app.use(bodyparser.json());
app.set('views', path.join(__dirname, '/views/'));
app.engine('hbs', exphbs({ extname: 'hbs', defaultLayout: 'mainLayout', layoutsDir: __dirname + '/views/layouts/' }));
app.set('view engine', 'hbs');
//render css files
app.use(express.static("public"));
app.listen(3000, () => {
console.log('Express server started at port : 3000');
});
app.use('/employee', employeeController);
employeeController.js file
const express = require('express');
var router = express.Router();
const mongoose = require('mongoose');
const Employee = mongoose.model('Employee');
//placeholders for added task
var task = ["complete presentation", "practise with nodejs"];
//placeholders for removed task
var complete = ["finish jquery"];
router.get('/', (req, res) => {
res.render("employee/addOrEdit", {
viewTitle: "Insert Module"
});
});
router.get('/test', (req, res) => {
res.render("employee/test");
});
//render the ejs and display added task, completed task
router.get("/index", function(req, res) {
res.render("index", { task: task, complete: complete });
});
router.post('/', (req, res) => {
if (req.body._id == '')
insertRecord(req, res);
else
updateRecord(req, res);
});
function insertRecord(req, res) {
var employee = new Employee();
employee.fullName = req.body.fullName;
employee.module = req.body.module;
employee.mobile = req.body.mobile;
employee.city = req.body.city;
employee.save((err, doc) => {
if (!err)
res.redirect('employee/list');
else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render("employee/addOrEdit", {
viewTitle: "Insert Module",
employee: req.body
});
}
else
console.log('Error during record insertion : ' + err);
}
});
}
function updateRecord(req, res) {
Employee.findOneAndUpdate({ _id: req.body._id }, req.body, { new: true }, (err, doc) => {
if (!err) { res.redirect('employee/list'); }
else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render("employee/addOrEdit", {
viewTitle: 'Update Module',
employee: req.body
});
}
else
console.log('Error during record update : ' + err);
}
});
}
router.get('/list', (req, res) => {
Employee.find((err, docs) => {
if (!err) {
res.render("employee/list", {
list: docs
});
}
else {
console.log('Error in retrieving module list :' + err);
}
});
});
function handleValidationError(err, body) {
for (field in err.errors) {
switch (err.errors[field].path) {
case 'fullName':
body['fullNameError'] = err.errors[field].message;
break;
case 'module':
body['moduleError'] = err.errors[field].message;
break;
default:
break;
}
}
}
router.get('/:id', (req, res) => {
Employee.findById(req.params.id, (err, doc) => {
if (!err) {
res.render("employee/addOrEdit", {
viewTitle: "Update Module",
employee: doc
});
}
});
});
router.get('/delete/:id', (req, res) => {
Employee.findByIdAndRemove(req.params.id, (err, doc) => {
if (!err) {
res.redirect('/employee/list');
}
else { console.log('Error in module delete :' + err); }
});
});
//post route for adding new task
router.post("/addtask", function(req, res) {
var newTask = req.body.newtask;
//add the new task from the post route
task.push(newTask);
res.redirect("/");
});
router.post("/removetask", function(req, res) {
var completeTask = req.body.check;
//check for the "typeof" the different completed task, then add into the complete task
if (typeof completeTask === "string") {
complete.push(completeTask);
//check if the completed task already exits in the task when checked, then remove it
task.splice(task.indexOf(completeTask), 1);
} else if (typeof completeTask === "object") {
for (var i = 0; i < completeTask.length; i++) {
complete.push(completeTask[i]);
task.splice(task.indexOf(completeTask[i]), 1);
}
}
res.redirect("/");
});
module.exports = router;
You need to add both engines, ejs and express-handlebars in your package.json file
npm i ejs
npm i express-handlebars
Import dependency in Server.js file
const ejs = require('ejs');
const exhbs = require('express-handlebars');
Set engine to your server.js file
app.set('view engine', 'ejs');
app.engine('handlebars', exhbs());
app.set('view engine', 'handlebars');
For rendering template, you need to set the file extension
res.render('heyy.handlebars');
res.render('index.ejs');
This is your Folder Structure
Inside main.handlebars and inside body add {{{body}}} inorder to mark where layout should insert page
I am trying to learn new things with Express and at this moment I would like to be able to show express messages. I added flash, session, and express-messages as dependencies and added messages as a locals variable.
In Pug, I added != messages('message'. locals) and according to the tutorial this should've output a div element with the messages, but unfortunately it throws an error "messages is not a function" when I tried to run it. I suppose req.flash('info','Article Added') in the index.js file on the server side will trigger the message.
this is the screenshot of the error I keep getting
Pls check if I'm getting anything wrong in my code, I'm stuck here. I had tried so much to find out what had caused it.
Here here is my app.js file
const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const expressValidator = require('express-validator');
const session = require('express-session');
const flash = require('connect-flash');
mongoose.connect('mongodb://localhost:27017/nodekb', { useNewUrlParser: true });
const db = mongoose.connection;
const app = express();
// app.dynamicHelpers({ messages: require('express-messages') });
//checking for db's connection
db.once('open', () => {
console.log('connected to mongo db');
});
//checking for db errors
db.on('error', (err) => {
console.log(err);
});
//setting up view engine directories
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
//bring in model
let Article = require('./models/articles')
//express routing and using the article model for home page
app.get('/', (req, res) => {
Article.find({}, (err, articles) => {
if (err) {
console.log(err)
} else {
res.render('index', {
title: 'Article',
articles: articles
});
}
});
});
//body parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
//seet public folder
app.use(express.static(path.join(__dirname, 'Public')));
//express session middleware
app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true
}))
//express message middleware
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
//
app.use(expressValidator({
errorFormatter: (param, msg, value) => {
var namespace = param.split('.'),
root = namespace.shift(),
formParam = root;
while (namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param: formParam,
msg: msg,
value: value
}
}
}))
//another route to add article
app.get('/article/add', (req, res) => {
res.render('add_article', {
title: 'Add Article'
});
});
//get single article
app.get('/article/:id', (req, res) => {
Article.findById(req.params.id, (err, article) => {
res.render('article', {
article: article
})
return;
});
});
//edit single article
app.get('/article/edit/:id', (req, res) => {
Article.findById(req.params.id, (err, article) => {
res.render('edit_article', {
title: 'Edit Article',
article: article
})
return;
});
});
//submit POST form from add_article.pug
app.post('/article/add', (req, res) => {
let article = new Article();
article.title = req.body.title;
article.author = req.body.author;
article.body = req.body.body;
article.save((err) => {
if (err) {
console.log(err);
} else {
req.flash('info', 'Article Added');
// res.send(article);
res.redirect('/');
}
})
});
//update POST form from edit_article.pug
app.post('/article/add/edit/:id', (req, res) => {
let article = {};
let query = { _id: req.params.id }
article.title = req.body.title;
article.author = req.body.author;
article.body = req.body.body;
Article.update(query, article, (err) => {
if (err) {
console.log(err);
} else {
req.flash('info', 'Article updated');
res.redirect('/');
}
})
});
app.delete('/article/:id', (req, res) => {
let query = { _id: req.params.id }
Article.remove(query, (err) => {
if (err) {
console.log(err);
};
res.send('sucess')
})
})
//setting up port
app.listen(3000, () => {
console.log('runnig on port 3000');
})
module.exports = app;
Here is my layout.pug where i am using the message
doctype html
html
head
title Knowledge base
link(rel='stylesheet', href='/bower_components/bootstrap/dist/css/bootstrap.css')
link(rel='stylesheet', href='/css/style.css')
body
nav.navbar.navbar-dark.bg-dark.navbar-expand-md
a.navbar-brand(href='#') Knowledge Base
button.navbar-toggler(type='button', data-toggle='collapse', data-target='#navbarsExample01', aria-controls='navbarsExample01', aria-expanded='false', aria-label='Toggle navigation')
span.navbar-toggler-icon
#navbarsExample01.collapse.navbar-collapse
ul.navbar-nav.ml-auto.pr-3
li.mr-2
a(href='/') Home
span.sr-only (current)
li.mr-2
a(href='/article/add') Add Articles
.container
!= messages('message', locals)
block content
br
hr
footer
p copyright © 2018
script(src='/bower_components/jquery/dist/jquery.js')
script(src='/bower_components/bootstrap/dist/js/bootstrap.js')
script(src='/js/main.js')
And finally the message.pug file referred to in Layout.pug
.messages
each type in Object.keys({messages})
each message in Object.values({messages})
div(class="alert alert-" +type) #{message}
You need to install the library express-messages
MEAN Stack
I keep getting
TypeError: Cannot read property 'first_name' of undefined
when trying to execute this code (all variables, including modules are defined in other parts of the code). While using GET Method, my code is working fine. But for POST Method, it throws error. Attached the screenshot below.
Advance Rest Client POST Method Exception
Added my code below.
Thanks in advance
//app.js
//Importing Modules
var express = require('express');
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var cors = require('cors');
var path = require('path');
var app = express();
//port Number
const port = 3000;
const route = require('./routes/route');
//Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/contactlist');
//if connected
mongoose.connection.on('connected', () => {
console.log("Mongo DB Connected successfully");
});
//if not connected
mongoose.connection.on('error', (err) => {
if (err) {
console.log('Error in connecting to the MongoDB');
}
});
//adding middleware cors
app.use(cors());
//routes will happen here
app.use('/api', route);
//adding middleware
app.use(bodyparser.json());
//Static files
app.use(express.static(path.join(__dirname, 'public')));
//Testing
app.get('/', (req, res) => {
res.send("Hello Vinoth");
});
app.get('/yahoo', (req, res) => {
res.send("Hello Vinoth");
});
//Connection
app.listen(port, () => {
console.log("Server started at port:" + port);
});
//route.js
const express = require('express');
const router = express.Router();
const Contact = require('../models/contacts');
// retrieving details
router.get('/contacts', (req, res, next) => {
Contact.find(function(err, contacts) {
res.json(contacts);
});
});
// Add Contacts
//Add contact
router.post('/contact', (res, req, next) => {
console.log('Insides');
let newContact = new Contact({
first_name: req.body.first_name,
last_name: req.body.last_name,
phone: req.body.phone
});
newContact.save((err, contact) => {
if (err) {
res.json({
msg: 'Failed to add contact'
});
} else {
res.json({
msg: 'Contact added successfully'
});
}
});
});
// Delete Contacts
router.delete('/contact/:id', (req, res, next) => {
Contact.remove({
_id: req.params.id
}, function(err, result) {
if (err) {
res.json(err);
} else {
res.json(result);
}
});
});
module.exports = router;
//contacts.js
const mongoose = require('mongoose');
const ContactSchema = mongoose.Schema({
first_name: {
type: String,
required: true
},
last_name: {
type: String,
required: true
},
phone: {
type: String,
required: true
}
});
const Contact = module.exports = mongoose.model('Contact', ContactSchema);
Try moving app.use(bodyparser.json()) before app.use('/api', route). Hope this helps.
First of all you need to Declare
//adding middleware
app.use(bodyparser.json());
Before use all routes. So you need to update your app.js like:
//adding middleware
app.use(bodyparser.json());
//routes will happen here
app.use('/api', route);
In additional you need to refactor your route.js
code like this:
//Add contact
router.post('/contact', (res, req, next) => {
const {
first_name,
last_name,
phone
} = req.body;
let newContact = new Contact({
first_name,
last_name,
phone
});
newContact.save((err, contact) => {
if (err) {
res.json({
msg: 'Failed to add contact'
});
} else {
res.json({
msg: 'Contact added successfully'
});
}
});
});