I have an issue where even when form validation fails the record is altered in the database.
Basically what I am trying to do is submit the form, get the data from the form fields and if validation fails, it should render the view with altered user input otherwise display data from the database for that record in the input fields.
Upon successful validation it should create a flash message to display to the user. I have added a few comments in the code for explanation as well.
exports.postEditListing = (req, res, next) => {
// get values from form input on form submission
const updatedTitle = req.body.title;
const updatedDescription = req.body.description;
const updatedCategory = req.body.category;
const image = req.file;
const productId = req.body.productId;
// creates slug from title field
const updatedSlugTitle = slugify(updatedTitle, {
lower: true,
remove: /[*+~.()'"!:@]/g
});
const errors = validationResult(req);
// if there ARE validation errors
if (!errors.isEmpty()) {
// Get categories from database where they aren't equal to what the user selected in the form
Category.find({ catName: { $ne: updatedCategory } })
.then(cats =>{
// render the view again showing the form data either updated by user if they edited fields or from the database
return res.status(422).render('account/edit-listing', {
pageTitle: 'Edit Listing',
path: '/account/edit-listing',
product: {
title: updatedTitle,
_id: productId,
category: updatedCategory,
description: updatedDescription
},
errorMessage: errors.array(),
successMessage: null,
pendingCount: req.pending,
approveCount: req.approved,
rejectCount: req.rejected,
userId: req.user._id,
cats: cats
});
})
.catch(err => {
console.log(err);
})
}
// If validation succeeds, find the product by ID in the database
Product.findById(productId)
.then(product => {
// set database fields to the updated form input values
product.title = updatedTitle;
product.description = updatedDescription;
product.titleSlug = updatedSlugTitle;
product.category = updatedCategory;
// if there is a new image selected, delete the existing one and set a new one
if (image) {
fileHelper.deleteFile(product.image);
product.image = image.path;
}
// save changes to database.
return product.save()
.then(result => {
// set flash message and redirect to the same page
req.flash('success', 'Category successfully added.');
res.redirect('/account/edit-listing/' + product._id);
console.log('success!');
});
})
.catch(err => {
// const error = new Error(err);
// error.httpStatusCode = 500;
// return next(error);
console.log(err);
});
};
The second issue is that if the fields are filled in correctly, an error still occurs:
unhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
UPDATE:
I have changed the above code and now I can see that success! shows in the console even if there is a validation error, meaning that this block of code runs when it actually should not get to this code at all if validation fails:
return product.save()
.then(result => {
// set flash message and redirect to the same page
req.flash('success', 'Category successfully added.');
res.redirect('/account/edit-listing/' + product._id);
console.log('success!');
});
About the first issue. You have an if
statement to check if validation fails. So you can add an else
statement after if
and execute the code you want only if validation is successful.