Back to Course |
Vue.js 3 + Laravel 11 + Vite: SPA CRUD

Delete Post with Confirmation Modal

Now that we can create and edit posts, let's make a delete post action, with the confirmation modal. For the confirmation modal, we will again use the sweetalert2.

delete modal confirmation


First, let's add a new destroy method in the PostController. Don't forget that we don't need to add any additional routes for this Controller methods, because all the routes come from the Route::apiResource() that we added earlier in the routes/api.php.

app/Http/Controllers/Api/PostController.php:

class PostController extends Controller
{
// ...
public function destroy(Post $post)
{
$post->delete();
 
return response()->noContent();
}
}

What to return in this method? It is an open question. It's a common practice to return nothing because the record is deleted. That response()->noContent() would return 204 HTTP Status Code.

Now in the posts Composable, we need to add a new method for deleting a post.

resources/js/composables/posts.js:

import { ref, inject } from 'vue'
import { useRouter } from 'vue-router'
 
export default function usePosts() {
const posts = ref({})
const post = ref({})
const router = useRouter()
const validationErrors = ref({})
const isLoading = ref(false)
const swal = inject('$swal')
 
// ...
 
const deletePost = async (id) => {
axios.delete('/api/posts/' + id)
.then(response => {
getPosts()
router.push({ name: 'posts.index' })
swal({
icon: 'success',
title: 'Post deleted successfully'
})
})
.catch(error => {
swal({
icon: 'error',
title: 'Something went wrong'
})
})
}
 
return {
posts,
post,
getPosts,
getPost,
storePost,
updatePost,
deletePost,
validationErrors,
isLoading
}
}

In this method, we haven't done anything new that wasn't already done in the previous methods. For the Axios HTTP request, we changed it to delete.

After successful deletion, we refresh the posts, redirect to the posts index page, and show the success message.

For the errors, we don't need to add them in the validationErrors variable, instead of that we just use sweetalert to show an error message.

Also, as you can see, we've changed the formatting of the return to one-per-line, as it became too long for inline syntax on one line.

Now, let's add a delete link to the posts table. When clicked, we need to call the deletePost method and pass the post ID to it.

resources/js/components/Posts/Index.vue:

<template>
// ...
 
<table class="min-w-full divide-y divide-gray-200 border">
 
// ...
 
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">
<router-link :to="{ name: 'posts.edit', params: { id: post.id } }">Edit</router-link>
<a href="#" @click.prevent="deletePost(post.id)" class="ml-2">Delete</a>
</td>
 
// ...
 
</table>
</template>
 
<script setup>
// ...
 
const selectedCategory = ref('')
const orderColumn = ref('created_at')
const orderDirection = ref('desc')
const { posts, getPosts } = usePosts()
const { posts, getPosts, deletePost } = usePosts()
const { categories, getCategories } = useCategories()
 
// ...
</script>

If you try to delete any post, now it should be deleted.

Finally, let's add a confirmation modal.

resources/js/composables/posts.js:

import { ref, inject } from 'vue'
import { useRouter } from 'vue-router'
 
export default function usePosts() {
const posts = ref({})
const post = ref({})
const router = useRouter()
const validationErrors = ref({})
const isLoading = ref(false)
const swal = inject('$swal')
 
// ...
 
const deletePost = async (id) => {
swal({
title: 'Are you sure?',
text: 'You won\'t be able to revert this action!',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Yes, delete it!',
confirmButtonColor: '#ef4444',
timer: 20000,
timerProgressBar: true,
reverseButtons: true
})
.then(result => {
if (result.isConfirmed) {
axios.delete('/api/posts/' + id)
.then(response => {
getPosts()
router.push({ name: 'posts.index' })
swal({
icon: 'success',
title: 'Post deleted successfully'
})
})
.catch(error => {
swal({
icon: 'error',
title: 'Something went wrong'
})
})
}
})
}
 
return {
posts,
post,
getPosts,
getPost,
storePost,
updatePost,
deletePost,
validationErrors,
isLoading
}
}

Before making the HTTP request, we call the sweetalert confirmation modal with some parameters. If the user doesn't press anything we have set a timer of 20000 ms. After the timer runs out, confirmation automatically applies. And then we check if the deletion was confirmed and delete the post.

delete modal confirmation