Has anybody combined their edit and create forms in a MEVN stack? For example Moongoose’s save method can create or update but I’m not sure how you handle passing in the ID if it does exist vs does not exist. Here is what I currently have for my create process & update process. It would be nice to combine two different componenets into one that did both jobs.
CreateStudent.vue
handleSubmitForm() {
console.log("handleSubmitForm")
this.isSubmitted = true;
let apiURL = "http://localhost:4000/api/create-student";
axios
.post(apiURL, this.student)
.then(() => {
this.$router.push("/list");
this.student = {
firstName: "",
lastName: "",
email: "",
phone: "",
password: "",
confirmPassword: "",
};
//alert("SUCCESS! " + JSON.stringify(this.userForm));
})
.catch((error) => {
console.log(error);
})
.finally((next) => {
// console.log('is Submiited);
})
},
studentRoute.route("/create-student").post((req, res, next) => {
StudentModel.create(req.body, (error, data) => {
if (error) {
return next(error);
} else {
res.json(data);
}
})
})
EditStudent.vue
handleUpdateForm() {
let apiURL = `http://localhost:4000/api/update-student/${this.$route.params.id}`;
axios.post(apiURL, this.student).then((res) => {
console.log(res)
this.$router.push('/list')
}).catch(error => {
console.log(error)
});
}
studentRoute.route('/update-student/:id').post((req, res, next) => {
StudentModel.findByIdAndUpdate(req.params.id, {
$set: req.body
}, (error, data) => {
if (error) {
return next(error);
} else {
res.json(data)
console.log('Student successfully updated!')
}
})
})
2
Answers
According to the docs you can simple send in an options to findByIdAndUpdate, one of them is upsert
https://mongoosejs.com/docs/api/model.html#Model.findByIdAndUpdate()
So something like
should work both as update or insert
It is better to handle updates and creates separately. @Bergur is correct in that
findOneAndUpdate
andfindByIdAndUpdate
have anupsert
option that will allow you to update or insert if no document matches. However, in my experience this typically works initially and then the problems start.The key sticking point is validation. With
findOneAndUpdate
andfindByIdAndUpdate
you can also pass therunValidators: true
option to tell mongoose to run the validators but this only works on fields included in the update document and only for some operations. So if you have a constraint on a field and you don’t pass that field in the update document then mongoose won’t do any validation. That can have some negative consequences.To illustrate a simple schema would look like:
Now if you do a
findOneAndUpdate
orfindByIdAndUpdate
like so:Then no validation is done on
veryImportantProperty
even with therunValidators
option because it wasn’t included inreq.body
so mongoose will create the document without it.Even if you use the
$set
operator like so:It will still save the new document without
veryImportantProperty
. WithModel.create()
you give yourself better data integrity, it’s easier to debug and you can send better error responses back to the user if a create operation fails.This is a simple example but with more complex validations things can get messy very quickly and it will be difficult to debug, especially if you revisit your codebase after some time away.