Im trying to create a comment function so that I can review products. I've gotten it to work in the back-end and I've tested the function through postman. But when I try to post via the form on the ejs, it fails the null constraints. I understand that my ejs tags are not provided with the correct data but I dont know how to solve the problem.
product-routes.js
/***********************************************************/
//get product by id
router.get('/product/:id', (req, res) => {
const id = req.params.id;
Product.findById(id).populate('reviews')
.then(result => {
res.render('product-details', { title: 'product details', product: result });
})
.catch(err => {
res.status(404).render('404', { title: '404' }); //renders the 404 page if product with id does not exist
console.log(err);
});
});
/***********************************************************/
//post review on post
router.post('/product/:id/review', (req, res) => {
const id = req.params.id;
const review = new Review(req.body);
//const currentUser = req.user;
review //create a new review
.save()
.then(() => Product.findById(id)) //find the product that is being reviewed
.then((result) => {
result.reviews.unshift(review); //append review details to this product, unshift puts the newest entry at the top
return result.save();
})
.then(() => res.redirect('back'))
.catch((err) => {
console.log(err);
});
});
/***********************************************************/
review-model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//schema for the review table in the mongoDB
const reviewSchema = new Schema({
comment: {
type: String,
required: true
},
rating: {
type: Number,
required: true,
enum: [1, 2, 3, 4, 5]
},
date: {
type: Date,
required: true,
default: Date.now
},
});
const Review = mongoose.model('Review', reviewSchema);
module.exports = Review;
product-details.ejs
<!-- looping through all our comments to show them in the table -->
<div >
<table >
<thead>
<tr>
<th scope="col">Comment</th>
<th scope="col">Rating</th>
<th scope="col">Date</th>
<th scope="col">Posted by:</th>
</tr>
</thead>
<tbody id="table-body">
<% product.reviews.forEach(review=> { %>
<tr>
<td>
<p>
<%= review.comment %>
</p>
</td>
<td>
<p>
<%= review.rating %>/5
</p>
</td>
<td>
<p>
<%= review.date %>
</p>
</td>
<td>
<p>placeholder</p>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<form action="/shop/product/<%= product._id %>/review" method="POST">
<textarea name="reviews[comment]" required></textarea>
<input type="number" name="reviews[rating]" min="1" max="5" step="1" required>
<input type="submit">
</form>
product-model.js (just in case)
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//add comment
const productSchema = new Schema({
title: {
type: String,
required: true
},
gender: {
type: String,
required: true
},
brand: {
type: String,
required: true
},
size: {
type:String,
required: true
},
picture: {
type: String,
required: true
},
description: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
//foreign key to retrieve an array of reviews on the product
reviews: [{
type: Schema.Types.ObjectId,
ref: 'Review'
}]
}, {timestamps: true });
const Product = mongoose.model('Product', productSchema);
module.exports = Product;
Error output:
Error: Review validation failed: rating: Path `rating` is required., comment: Path `comment` is required.
at ValidationError.inspect (C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\error\validation.js:48:26)
at formatValue (node:internal/util/inspect:780:19)
at inspect (node:internal/util/inspect:345:10)
at formatWithOptionsInternal (node:internal/util/inspect:2165:40)
at formatWithOptions (node:internal/util/inspect:2027:10)
at console.value (node:internal/console/constructor:324:14)
at console.log (node:internal/console/constructor:360:61)
at C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\routes\product-routes.js:114:21
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
errors: {
rating: ValidatorError: Path `rating` is required.
at validate (C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\schematype.js:1322:13)
at C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\schematype.js:1305:7
at Array.forEach (<anonymous>)
at SchemaNumber.SchemaType.doValidate (C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\schematype.js:1255:14)
at C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\document.js:2745:18
at processTicksAndRejections (node:internal/process/task_queues:78:11) {
properties: [Object],
kind: 'required',
path: 'rating',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
},
comment: ValidatorError: Path `comment` is required.
at validate (C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\schematype.js:1322:13)
at C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\schematype.js:1305:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\schematype.js:1255:14)
at C:\Users\Karwan Gara\Studier\År 3\GIK2PG (Projektbaserad systemutveckling)\Latest working\Sneakers-Ecommerce-Website\node_modules\mongoose\lib\document.js:2745:18
at processTicksAndRejections (node:internal/process/task_queues:78:11) {
properties: [Object],
kind: 'required',
path: 'comment',
at runMicrotasks (<anonymous>)
CodePudding user response:
You need to use use app.use(express.urlencoded({ extended: true }));
CodePudding user response:
Try changing the form input names. from name="reviews[comment]"
to name="comment"
and from name="reviews[rating]"
to name="rating"