VDOM Stack (Vue Deno Oak MongoDB) CRUD example
In our last two articles, we learned the create and fetch the contact details in VDOM stack application. In this article, we are going to implement the remaining edit and delete part of this CRUD series.

Add edit contact concept in contact.ts in model folder
1 2 3 4 5 |
editContact = async (contactId: string) => { return await this.contactCollection.findOne({ _id: { $oid: contactId }, }); }; |
Create editContact function in controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
export const editContact: any = async(response: any) =>{ try{ let contactId: string = response.params.contactid; const data: any = await ContactClass.editContact(contactId); if(data){ response.response.body = data; response.response.status = 200; } } catch(e){ response.response.body = null; response.response.status = 500; } } |
Add edit contact routes:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import { Router } from "https://deno.land/x/oak/mod.ts"; import { getContacts, createContact, editContact } from "../controllers/contacts.ts"; const router = new Router({ prefix: "/api", }); router .get("/contacts", getContacts) .get('/edit/:contactid', editContact) .post("/create", createContact); export default router; |
Now it’s time to work on the UI part of editComponent.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<template> <div class="row justify-content-center"> <div class="col-md-6"> <h3 class="text-center">Create Contact</h3> <form @submit.prevent="update"> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" v-model="contact.firstname" required /> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" v-model="contact.lastname" required /> </div> <div class="form-group"> <label for="email">Email</label> <input type="text" class="form-control" v-model="contact.email" required /> </div> <div class="form-group"> <label for="phone">Phone</label> <input type="text" class="form-control" v-model="contact.phone" required /> </div> <div class="form-group"> <button class="btn btn-success btn-block">Update</button> </div> </form> </div> </div> </template> <script> import axios from "axios"; export default { data() { return { contact: {}, }; }, created(){ let apiUrl = `http://localhost:4000/api/edit/${this.$route.params.id}`; axios.get(apiUrl).then((res) =>{ this.contact = res.data; }) }, methods: {}, }; </script> |
Now it’s time to update the contact. Add below code in contact.ts in model.
1 2 3 4 5 6 7 8 |
updateContact = async (contactId: string, changeData: Contact) => { const { matchedCount, modifiedCount, userId } = await this.contactCollection .updateOne( { _id: { $oid: contactId } }, { $set: changeData }, ); return matchedCount !== 0 ? true : false; }; |
Now add update contact in controller.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
export const updateContact = async({request, response, params}: {request: any, response: any, params: any})=>{ const contactId = await params.contactId; const requestBody = await request.body({ contentTypes: { text: ["application/ld+json"] } }); const contact = requestBody.value; const updateContact = await ContactClass.updateContact(contactId, contact); if(updateContact == true){ response.status = 200; response.body = { msg: "Contact has been updated" } } else{ response.status = 404; response.body = { msg: "Contact not found"; } } } |
Add patch routes in contact.ts inside routes folder
1 2 3 4 5 6 |
router .get("/contacts", getContacts) .get("/edit/:contactid", editContact) .post("/create", createContact) .patch("/update/:contactId", updateContact) ; |
Next thing is to add update method in EditComponent.vue
1 2 3 4 5 6 7 |
update() { let apiUrl = `http://localhost:4000/api/update/${this.$route.params.id}`; axios.patch(apiUrl, this.contact).then((res)=>{ console.log(res); this.$router.push('contacts'); }).catch((err)=>console.log(err)); } |
Now your update section of this stack is completed. Now it’s time to complete our last delete functionality in our application.
Create deleteContact in the models>contact.ts
1 2 3 4 5 6 |
deleteContact = async (contactId: string) => { const isContactDeleted = await this.contactCollection.deleteOne({ _id: { $oid: contactId }, }); return isContactDeleted ? true : false; }; |
After model, add deleteContact method in controller of contacts.ts
1 2 3 4 5 6 7 8 9 10 11 12 |
export const deleteContact = async({request, response, params} : {request: any, response: any, params: any})=>{ const contactId = await params.contactId; const deleteContact = await ContactClass.deleteContact(contactId); if(deleteContact){ response.status = 200; response.body = { msg: "Contact has been deleted"} } else{ response.status = 404; response.body = { msg: "Contact not found"} } } |
Now enable the delete link in routes
1 2 3 4 5 6 |
router .get("/contacts", getContacts) .get("/edit/:contactid", editContact) .post("/create", createContact) .patch("/update/:contactId", updateContact) .delete("/delete/:contactId", deleteContact); |
At last complete the delete button in the ContactComponent.vue
1 |
<button class="btn btn-danger" @click.prevent="deleteContact(contact._id.$oid)">Delete</button> |
Wait! Have you call the delete service? No, then how your delete will work. Let me finish the last piece of code.
Add deleteContact method in ContactComponet.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
methods: { deleteContact(id) { let apiUrl = `http://localhost:4000/api/delete/${id}`; let indexOfArrayItem = this.contacts.findIndex((i) => i._id.$oid === id); if (window.confirm("Do you want to delete?")) { axios .delete(apiUrl) .then(() => { this.contacts.splice(indexOfArrayItem, 1); }) .catch((err) => { console.log(err); }); } }, }, |
Video of this code:
As I told you, source code of this series.

