DELETE Request with nodejs and Mongoose - javascript

I'm struggling to delete a row from a collection of my database using mongoose. The console said that deleting was successful (as I handled error), but when I check my database, the row is still here. I successfully add a member with a post request, but I was not able to delete it.
I suspect my route file or my hbs file.
Here is the code :
Index.js (the route part)
app.get('/delete',(req,res) => res.render('delete', {
title:'Member App',
}));
routes/members.js
// Delete member : DELETE
router.get("/delete", (req,res)=>{
console.log(req.params.id);
Member.deleteOne({ _id: req.params.id }, function(err,data) {
if (!err) {
console.log(data);
console.log("member successfully deleted")
}
else {
console.log("error")
}
});
res.redirect("/");
});
delete.hbs
<h1 class = "text-center mb-3">{{title}}</h1>
<form action="/delete" method ="DELETE" class="mb-4">
<div class="form-group">
<label for="Id">Id</label>
<input type="Id" name="Id" class ="form-control">
</div>
<input type="submit" value ="Delete member" class="btn">
</form>
The console : (it seems that the data from my callback is undefined)
Connected to mongoDB
undefined
{ n: 0, ok: 1, deletedCount: 0 }
member successfully deleted

Your input type tag is wrong.
<input type="Id" name="Id" class ="form-control">
There is no "Id" type in input (see input types values)
You don't use correct field
req.params.id
Is used, but I don't see any params in your request.
You only have the body filled with Id so in order to use it, you should call :
req.body.Id

First of all the absence of an error does not guarantee the deletion of a record in the database. So in this case prefer to use findOneAndRemove method.
Second res.redirect("/"); will called before record removing has done, so redirect should be moved into callback function like:
Member.findOneAndRemove({ _id: req.params.id }, function(err, member) {
if (!err && member) {
console.log(member);
console.log("member successfully deleted")
}
else {
console.log("error")
}
res.redirect("/");
});

Related

My req.body object is showing as empty when I submit a PUT request. I am using the method override middlware

I am trying to update a form using the put method. I am using method override middleware to make my form use a PUT request instead of a POST. when I console log the req.body to see if any information is coming through its empty.
Here is my ejs code:
<form action="/edit/<%= topic._id %>" method="post" class="formCard card">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="Make Edit" class="btn btn-dark">
</form>
I removed the input data since its not necassary.
Here is my express PUT method:
router.put('/edit/:id', async (req, res) => {
let topic = await Topic.findById(req.params.id)
topic = await Topic.findOneAndUpdate({_id: req.params.id}, req.body, {
new: true,
runValidators: true
})
console.log(req.body)
})
I am also using :
app.use(express.urlencoded({extended: true}))
app.use(express.json())
why am I not able to perform a update? Im confused on why the req.body is empty and not the updated fields in my form when I click the submit button?
I actually forgot to add the "name" attribute to my inputs! I can't believe I forgot that. When working with a form when the request gets sent it grabs those name fields. That's why the payload was empty.
router.put('/edit/:id', (req, res) => {
Topic.findByIdAndUpdate({_id: req.params.id}, req.body).then( function() {
Topic.findOne({_id: req.params.id}).then(topics => {
res.send(topics);
});
});
});
Did you try this way?

findByIdAndRemove resulting in an Error

Can anyone please help spot why the mongoose findByIdAndRemove in the delete route below...
//DELETE Route
app.delete("/blogs/:id", function(req, res){
//Destroy blog
Blog.findByIdAndRemove(req.params.id, function(err){
if(err){
res.send(err);
} else {
res.redirect("/blogs");
}
});
});
...generates the error below:
message: "Cast to ObjectId failed for value "5a6a8f967c9a190507b03433 " at path "_id" for model "Blog"",
name: "CastError",
stringValue: ""5a6a8f967c9a190507b03433 "",
kind: "ObjectId",
value: "5a6a8f967c9a190507b03433 ",
path: "_id"
Many thanks in anticipation of your help.
The problem is that you're sending a 16 character long String from the client while the method findOneByIdAndRemove demands an ObjectId. Doing this will eradicate the issue,
var mongoose = require('mongoose'); //remove it as you might already it
var ObjectId = mongoose.Types.ObjectId;
app.delete("/blogs/:id", function(req, res){
//Destroy blog
Blog.findByIdAndRemove(ObjectId(req.params.id), function(err){
if(err){
res.send(err);
} else {
res.redirect("/blogs");
}
});
});
Also, make sure that the _id is 16 character long, no spaces on either side is allowed.
Many thanks #vicbyte and Nilesh Singh for your contributions.
Indeed the code was failing due to the space at the end of the id: "5a6a8f967c9a190507b03433 ". The space came from the form issuing the DELETE:
<form id="delete" action="/blogs/<%= blog.id %> ?_method=DELETE" Method ="POST">
<button class = "ui red basic button">Delete</button>
</form>
Revising the the form as below...
<form id="delete" action="/blogs/<%= blog.id %>?_method=DELETE" Method ="POST">
<button class = "ui red basic button">Delete</button>
</form>
...cleared the error.
use async await. For Example:
async function(req,res) {
await Blog.findByIdAndRemove();
}

Sending a DELETE request with EJS using Mongoose

So I have already made a Restful API with node and everything works but I am trying to add EJS to it so I can use HTML&CSS, I implemented GET and POST just fine but I am tripping up on DELETE.
Here is my code in my router to delete
listRouter.delete('/:id',
function(req, res) {
req.list = list;
req.list.remove(function(err){
if (err)
res.status(500).send(err);
else
res.redirect('/')
});
});
and here's my EJS for deletion
<form method="DELETE" action="/:id">
<button type="submit">Delete</button>
</form>
and this is the error I receive when I press the button
{
message: "Cast to ObjectId failed for value ":id" at path "_id"",
name: "CastError",
kind: "ObjectId",
value: ":id",
path: "_id"
}
The thing is though the same exact code works if it's modified for JSON so I don't know if its EJS or my Javascript.
Thanks
i think html5 just support post and get in method form attribute
however, in my case if i don't using form for submit, here example
example in html or front end
<a class="btn btn-raised btn-danger" href="/admin/dashboard/detele/<%= data.userId %>">Delete</a></td>
<!-- The href needs to point at a link where data.userId is shown. Hence you need the = after <% for ejs to show the variable. -->
In app.js for the url delete
app.get('/admin/dashboard/detele/:id', users.deleteUser);
in express users.js
exports.deleteUser = function(req, res) {
users.findOneAndRemove({
userId: req.params.id
}, function(err, user) {
if (err) throw err;
console.log("Success");
});
res.redirect('/admin/dashboard');
}
don't forget creating mongo model for mongoose
var skema = new mongo.Schema({
name: String,
email: String,
password: String,
date: {
type: Date,
default: Date.now
},
admin: Boolean
});
var users = mongo.model('accounts', skema);
i using EJS here, hope it's help you
more helpful link1
more helpful link2
giving up use of method-override can be solution
I used different url to solve this.
<form action="/quake/forum/update/<%= post._id %>?_method=put" method="post">
and
<form action="/quake/forum/delete/<%= post._id %>?_method=delete" method="post" class="d-inline">
and router
main router
app.use('/quake/forum',forumRouter); //this is for just making sure explaination clear
sub router (forumRouter)
router.post('/delete/:id', function (req, res) {
and
router.post('/update/:id', function (req, res) {

Routing to a specific user profile using iron router (METEOR)

As the question says, I need to create a specific route for every user that I have. In my case employers. Now all the examples on the web are connected with the USERS collection.
In my case I want to route to: "/employer/:_id" but I have the Employer ID in the Collection Employers. So basically I have to get the Employer ID via the key from User ID
Im kinda stuck on returning the Employer ID value to the route...
METHODS.js
getEmployerId: function(currentuser){
employerId = Employer.find({"user":currentuser}).fetch();
return employerId;
}
ROUTER.js
Router.route("/employer/:_id", {
name:"employer",
template:"employer",
layoutTemplate:'employerLayout',
data: function(){
var currentuser = Meteor.userId();
Meteor.call("getEmployerId", currentuser, function(error, result){
if(error){
console.log("error", error);
}
if(result){
return true; // I belive here is where I have to pass it up to the ROUTE
}
});
},
onBeforeAction:function(){
var user = Meteor.userId();
if(!user || !Roles.userIsInRole(user, ['employer'])) {
Router.go("verification");
}else {
this.next();
}
return true;
},
});
And this is how my Employer collection looks like:
meteor:PRIMARY> db.employer.find().pretty()
{
"_id" : "qCFGZa4ogc5LR56PL", // I need this for the route
"createdAt" : ISODate("2015-07-18T13:19:16.098Z"),
"user" : "owfJ4ozrfsp26o8G4" // the key through which i can return the ID, got it from the user session?
}
Anyone has a suggestion how to do this? And is this a good approach for each user(employer) profile? Any tutorial, example or anything that describes an application with user profiles would be much appriciated!
Ok, looks like you're nearly there.
I don't think you want the ::id parameter. You send the user to simply /employer, where he does the sign in, so you have his user id.
Then change getEmployerId to getEmployer: in other words, get the whole of the employer record.
getEmployer: function(currentuser){
return Employer.find({"user":currentuser}).fetch();
}
Then in your data: function of the router instead of returning true you return the record you find. In this way the record is available for your template (that's what the data function is for)
data: function(){
var currentuser = Meteor.userId();
Meteor.call("getEmployer", currentuser, function(error, result){
if(error){
console.log("error", error);
}
if(result){
return result;
}
});
},

Insert form data into mysql database table using node.js and sequelize

I have a NodeJS app and I want to insert some data from a form into a table of my MySQL-database by using the sequelize()-method.
So here is my form
<form id="addVideo" method="post">
<input type="url" name="video_url" required></input>
<input type="hidden" value="" name="artist_id"></input>
<input type="hidden" value="youtube" name="type"></input>
</form>
My post function:
$('form#addVideo').submit(function(e){
e.preventDefault();
var form = $(this);
var jsonvideoFormData = utils.serializeToJSON(form);
var xhrData = _.pick(jsonvideoFormData, 'video_url', 'artist_id', 'type');
api.post('/videos', xhrData, function(response){
alert('Video has been added!');
});
});
Then the backend code looks like this:
exports.addVideo = function(req, res, next){
var videoURL = req.body.video_url;
var artistId = req.body.artist_id;
var type = req.body.type;
db.sequelize.query('INSERT INTO social_urls (artist_id,urls,type) VALUES('artistId','videoURL','type')', function(err) {
if(err){
return res.json(400, {response: {code: 400, message:'An error appeared.'}});
} else{
console.log('succes');
res.json(201, {response: {code: 201, message: 'Video has been added'}});
}
});
}
But for some reason I do not know this is not working. Can anyone help me out?
Many thanks!!
I am not an expert in sequelize, but I see there code prone to SQL Injection.
This is wrong:
db.sequelize.query('INSERT INTO social_urls (artist_id,urls,type) VALUES('artistId','videoURL','type')', function(err)
It should be, at least:
db.sequelize.query("INSERT INTO social_urls (artist_id,urls,type) VALUES('" + artistId + "','" + videoURL + "','" + type + "')'", function(err)
But really, I think you should be doing something like this:
var SocialUrl = sequelize.define('SocialUrl', {
videoURL: Sequelize.STRING,
artistId: Sequelize.STRING,
type: Sequelize.STRING
}, {
tableName: 'social_urls',
timestamps: false
});
SocialUrl
.create({
videoURL: videoURL,
artistId: artistId,
type: type
})
.complete(function(err, socialUrl) {
if (err) {
// log error;
} else {
// Do stuff
}
})
this is the actual query to save the data. Steps 2 & 3.
var videoURL = req.body.video_url;
var artistId = req.body.artist_id;
var type = req.body.type;
models.socialUrls.build({
artist_id: artistId,
urls: videoURL,
type: type
})
.save()
.then(anotherTask => {
console.log('the data saved!');
// you can now access the currently saved task with the variable anotherTask... nice!
})
.catch(error => {
console.log('uh oh something wasn't right!');
console.log(error);
// Ooops, do some error-handling
})
If you check out the sequelize docs here:
http://docs.sequelizejs.com/manual/tutorial/instances.html
There are 3 steps to saving the data.
Creating the model
Creating the instance, a.k.a data object within your callback. This is what gets sent to sequelize method to send to db.
Calling the .save() method.
After that you can handle the errors with .catch()
From what it looks like your problem is in your backend code. Make sure your model is correct and the data from your form is getting sent. Once you are sure of that you only need to do steps 2 and 3.
You don't have to JSON serialize data. You can just post the data.
<form id="addVideo" method="post" action="/videos">
<input type="url" name="video_url" required></input>
<input type="hidden" value="" name="artist_id"></input>
<input type="hidden" value="youtube" name="type"></input>
</form>
Remeber to use body-parser
app.use(require("body-parser")());
Now req.body.video_url should have the expected data.

Categories