Now, let's build the page to edit the task. It will be structurally similar to the Create form but with a few differences.
Also, at the end of this lesson, we will add breadcrumbs above the table.
Table: Link to Edit Route
We need to add the "Edit" button to the table.
<TableRow v-for="task in tasks" :key="task.id"> <TableCell>{{ task.name }}</TableCell> <TableCell :class="{ 'text-green-600': task.is_completed, 'text-red-700': !task.is_completed }"> {{ task.is_completed ? 'Completed' : 'In Progress' }} </TableCell> <TableCell class="text-right"> <TableCell class="flex gap-x-2 text-right"> <Link :class="buttonVariants({ variant: 'default' })" :href="`/tasks/${task.id}/edit`">Edit </Link> <Button variant="destructive" @click="deleteTask(task.id)" class="mr-2">Delete </Button> </TableCell></TableRow>
Here's the visual result:
Edit Page: Vue Component
The previous code snippet above shows the URL /tasks/${task.id}/edit
. This corresponds to the Controller method edit()
, which uses Route Model Binding to find the task.
app/Http/Controllers/TaskController.php
public function edit(Task $task){ return Inertia::render('Tasks/Edit', [ 'task' => $task, ]);}
Now, we need to create the Tasks/Edit.vue
Vue component. I will just show you the full code here. Most of it is identical to the Tasks/Create.vue
component, except for the new is_completed
checkbox.
resources/js/pages/Tasks/Edit.vue:
<script setup lang="ts">import InputError from '@/components/InputError.vue';import { Button } from '@/components/ui/button';import { Checkbox } from '@/components/ui/checkbox';import { Input } from '@/components/ui/input';import { Label } from '@/components/ui/label';import AppLayout from '@/layouts/AppLayout.vue';import { Task } from '@/types';import { Head, useForm } from '@inertiajs/vue3'; interface Props { task: Task;} const props = defineProps<Props>(); const task = props.task; const form = useForm({ name: task.name, is_completed: task.is_completed,}); const submitForm = () => { form.put(route('tasks.update', task.id), { preserveScroll: true, });};</script> <template> <AppLayout> <Head title="Edit Task" /> <div class="flex h-full flex-1 flex-col gap-4 rounded-xl p-4"> <form class="space-y-6" @submit.prevent="submitForm"> <div class="grid gap-2"> <Label htmlFor="name">Task Name *</Label> <Input id="name" v-model="form.name" class="mt-1 block w-full" /> <InputError :message="form.errors.name" /> </div> <div class="grid gap-2"> <Label htmlFor="is_completed">Completed?</Label> <Checkbox id="is_completed" v-model:checked="form.is_completed" class="mt-1" /> <InputError :message="form.errors.is_completed" /> </div> <div class="flex items-center gap-4"> <Button :disabled="form.processing" variant="default">Update Task</Button> </div> </form> </div> </AppLayout></template>
As I mentioned, the differences are:
- New
<Checkbox>
component from the same Shadcn - Different method name
editTask
and routeroute('tasks.update', task.id)
to update the task
Here's the visual result:
That's it. We have built the full CRUD!
Quick "Bonus" 1: Switch Checkbox
Instead of a regular checkbox, you may want to choose the Shadcn component called Switch.
This would be the visual result:
To achieve this, just install the componen
npx shadcn-vue@latest add switch
And in the Edit.vue
file, all you need to do is change the Checkbox
to Switch
in two places: the import and the usage. All the parameters are identical.
resources/js/pages/Tasks/Edit.vue:
import { Checkbox } from '@/components/ui/checkbox';import { Switch } from '@/components/ui/switch'; // ... <Checkbox id="is_completed" v-model:checked="form.is_completed" class="mt-1" /><Switch id="is_completed" v-model="form.is_completed" class="mt-1" />
Quick "Bonus" 2: Breadcrumbs
To make UX a bit better, we will add the path breadcrumbs on top:
It's very easy in the Laravel starter kit, so we will do it on all three pages: Tasks Index, Create, and Edit.
There's a TypeScript type BreadcrumbItem
already defined in the types file:
resources/js/types/index.d.ts:
export interface BreadcrumbItem { title: string; href: string;}
So, we import it into our page components.
Then, we define our Breadcrumb items with their paths.
And the final step is just to pass the breadcrumbs as a parameter to the main <AppLayout>
component.
resources/js/pages/Tasks/Index.vue:
import { type BreadcrumbItem, Task } from '@/types'; // ... const breadcrumbs: BreadcrumbItem[] = [ { title: 'Dashboard', href: '/dashboard' }, { title: 'Tasks', href: '/tasks' },]; // ...</script> <template> <AppLayout :breadcrumbs="breadcrumbs">
And that's it!
We repeat (almost) the same in the other two pages.
resources/js/pages/Tasks/Create.vue:
import { type BreadcrumbItem } from '@/types'; // ... const breadcrumbs: BreadcrumbItem[] = [ { title: 'Dashboard', href: '/dashboard' }, { title: 'Tasks', href: '/tasks' }, { title: 'Create', href: '/tasks' },]; // ... <AppLayout :breadcrumbs="breadcrumbs"> // ...
resources/js/pages/Tasks/Edit.vue:
import { type Task } from '@/types'; import { type BreadcrumbItem, type Task } from '@/types'; // ... const breadcrumbs: BreadcrumbItem[] = [ { title: 'Dashboard', href: '/dashboard' }, { title: 'Tasks', href: '/tasks' }, { title: 'Edit', href: '' },]; // ... <AppLayout :breadcrumbs="breadcrumbs">// ...
So yeah, this is how easy it is to add breadcrumbs to the Vue starter kit.
Here are the GitHub commits for the Edit form, Switch and for the Breadcrumbs.
That's it for this section: we've created a simple CRUD.
In the next lessons, we will add more elements to that CRUD:
- Pagination
- More fields/components: Date Picker, File Upload, Select
- Add widgets on Dashboard
- ... and more
No comments yet…