Another common feature is deleting a record with a confirmation message.
First, let's take care of the back-end part.
app/Http/Controllers/PostController.php:
class PostController extends Controller{ // ... public function destroy(Post $post) { $post->delete(); return redirect()->route('posts.index') ->with('message', 'Post deleted successfully'); }}
For the front-end, first, let's add the button.
resources/js/Pages/Posts/Index.vue:
// ... <template> <Head title="Posts" /> <AppLayout> <Link :href="route('posts.create')" class="mb-4 inline-block rounded-md bg-blue-500 px-4 py-3 text-xs font-semibold uppercase tracking-widest text-white shadow-sm"> Add new post </Link> <table class="min-w-full border divide-y divide-gray-200"> <thead> <tr> <th class="bg-gray-50 px-6 py-3 text-left"> <span class="text-xs font-medium uppercase leading-4 tracking-wider text-gray-500">ID</span> </th> <th class="bg-gray-50 px-6 py-3 text-left"> <span class="text-xs font-medium uppercase leading-4 tracking-wider text-gray-500">Title</span> </th> <th class="bg-gray-50 px-6 py-3 text-left"> <span class="text-xs font-medium uppercase leading-4 tracking-wider text-gray-500">Content</span> </th> <th class="bg-gray-50 px-6 py-3 text-left"> <span class="text-xs font-medium uppercase leading-4 tracking-wider text-gray-500">Created At</span> </th> <th class="bg-gray-50 px-6 py-3 text-left"></th> </tr> </thead> <tbody class="bg-white divide-y divide-gray-200 divide-solid"> <tr v-for="post in posts.data"> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> {{ post.id }} </td> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> {{ post.title }} </td> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> {{ post.content }} </td> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> {{ post.created_at }} </td> <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> <button type="button" class="rounded-md bg-red-600 px-3 py-2 text-xs font-semibold uppercase tracking-widest text-white shadow-sm"> Delete </button> </td> </tr> </tbody> </table> </AppLayout></template>
The delete button will have a click event. When the button is clicked, we can use the form helper again, but this time, we will make a manual visit.
For that, we will create a function destroy()
, which will accept the id
as a parameter and call it when the button clicks.
resources/js/Pages/Posts/Index.vue:
<script setup>import AppLayout from '../../Layouts/App.vue';import { Head, Link } from '@inertiajs/vue3'; const props = defineProps({ posts: { type: Object, required: true }}) const destroy = (id) => { }</script> <template>// ... <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap"> <button type="button" class="rounded-md bg-red-600 px-3 py-2 text-xs font-semibold uppercase tracking-widest text-white shadow-sm"> <button @click="destroy(post.id)" type="button" class="rounded-md bg-red-600 px-3 py-2 text-xs font-semibold uppercase tracking-widest text-white shadow-sm"> Delete </button></td> // ...</template>
In the destroy()
function, we will use the native browser confirmation and, after confirming, call the delete method for the posts.destroy
route.
resources/js/Pages/Posts/Index.vue:
<script setup>import AppLayout from '../../Layouts/App.vue';import { Head, Link } from '@inertiajs/vue3'; import { Head, Link, router } from '@inertiajs/vue3'; const props = defineProps({ posts: { type: Object, required: true }}) const destroy = (id) => { if (confirm('Are you sure?')) { router.delete(route('posts.destroy', id)) }}</script> // ...
After pressing the delete button, confirmation is shown.
After confirming the delete, the post is deleted, and a success message appears. And the main thing of SPA and Inertia: it all happened without a full page refresh.
So this is how we can perform the delete, and this is also how you can process the form manually if, for some reason, you don't want to use the form helper from Inertia.