Hello Artisan,
In the previous blog post, we saw how to set laravel + inertia js project to create a crud operation. If you haven't read it yet, then you can read it here Laravel 11 + Inertia JS (VUE) CRUD Example: Part 1
and configure a basic setup. In this part 2 series, we will build the frontend and backend logic and see how easily inertia seamlessly communicates with the laravel.
Step 1: Create an Event Controller and add the routes in web.php
php artisan make:controller EventController
This route will used to create, read, update, delete events.
// web.php
Route::get('/event', [EventManagementController::class, 'index'])
->name('event.index');
Route::get('/event/create', [EventManagementController::class, 'create'])
->name('event.create');
Route::post('/event/create', [EventManagementController::class, 'store'])
->name('event.store');
Route::get('/event/{event}', [EventManagementController::class, 'show'])
->name('event.show');
Route::get('/event/{event}/edit', [EventManagementController::class, 'edit'])
->name('event.edit');
Route::put('/event/{event}/update', [EventManagementController::class, 'update'])
->name('event.update');
Route::delete('/event/{event}/delete', [EventManagementController::class, 'delete'])
->name('event.delete');
Step 2: Create a frontend design to create an event using Inertia.
- Create a new folder and name it
EventManagement
in this given pathresources\js\Pages
and within that folder create a vue component asCreate.vue
and add the below code in that component.
<script setup>
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
import { Head, useForm } from "@inertiajs/vue3";
import VueDatePicker from "@vuepic/vue-datepicker";
const form = useForm({
name: "",
location: "",
startDate: "",
endDate: "",
});
const save = () => {
form.post(route("event.store"), {
onFinish: () => form.reset(),
});
};
</script>
<template>
<Head title="Event Management" />
<AuthenticatedLayout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Create Event
</h2>
</template>
<div class="p-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<form @submit.prevent="save">
<div class="space-y-12 p-12">
<div class="border-b border-gray-900/10 pb-12">
<h2
class="text-base font-semibold leading-7 text-gray-900"
>
Event
</h2>
<p class="mt-1 text-sm leading-6 text-gray-600">
Add event details here
</p>
<div
class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"
>
<div class="sm:col-span-3">
<label
for="name"
class="block text-sm font-medium leading-6 text-gray-900"
>Event name</label
>
<div class="mt-2">
<input
type="text"
v-model="form.name"
id="name"
autocomplete="event name"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div class="sm:col-span-3">
<label
for="location"
class="block text-sm font-medium leading-6 text-gray-900"
>Location</label
>
<div class="mt-2">
<input
type="text"
v-model="form.location"
id="location"
autocomplete="location"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div class="sm:col-span-3">
<label
for="start-date"
class="block text-sm font-medium leading-6 text-gray-900"
>Start Date</label
>
<VueDatePicker
v-model="form.startDate"
/>
</div>
<div class="sm:col-span-3">
<label
for="end-date"
class="block text-sm font-medium leading-6 text-gray-900"
>End date</label
>
<VueDatePicker v-model="form.endDate" />
</div>
</div>
</div>
<div
class="mt-6 flex items-center justify-end gap-x-6"
>
<button
type="button"
class="text-sm font-semibold leading-6 text-gray-900"
>
Cancel
</button>
<button
type="submit"
class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
Save
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</AuthenticatedLayout>
</template>
- Add the backend code to
EventController
in thestore
method.
public function store(Request $request)
{
$params = $request->all();
$data = [
'name' => $params['name'],
'from_datetime' => $params['startDate'],
'to_datetime' => $params['endDate'],
'location' => $params['location'],
];
Event::create($data);
return redirect()->route('event.index');
}
Step 3: Create a listing page to show the events. Create Index.vue
component and add the code below.
<script setup>
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
import { Head, Link, useForm } from "@inertiajs/vue3";
import DangerButton from "@/Components/DangerButton.vue";
import moment from "moment-js";
defineProps({
events: {
type: Array,
},
});
const form = useForm({});
const deleteEvent = (id) => {
if (confirm("Are you sure you want to move this to trash")) {
form.delete(route("event.delete", { id: id }), {
preserveScroll: true,
});
}
};
const formatDate = (date) => {
return moment(date).format("MM/DD/YYYY hh:mm");
};
</script>
<template>
<Head title="Event Management" />
<AuthenticatedLayout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Event Management
</h2>
</template>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="flex justify-between">
<div class="p-6 text-gray-900">List of events</div>
<div class="my-auto px-5">
<Link
:href="route('event.create')"
class="p-3 rounded my-auto text-white bg-blue-500"
>
Create Event
</Link>
</div>
</div>
<div class="flex flex-col p-6">
<div class="overflow-x-auto sm:-mx-6 lg:-mx-8">
<div
class="inline-block min-w-full py-2 sm:px-6 lg:px-8"
>
<div class="overflow-hidden">
<table
class="min-w-full border rounded text-left text-sm font-light text-surface dark:text-white"
>
<thead
class="border-b border-neutral-200 font-medium dark:border-white/10"
>
<tr>
<th
scope="col"
class="px-6 py-4"
>
#
</th>
<th
scope="col"
class="px-6 py-4"
>
Event Name
</th>
<th
scope="col"
class="px-6 py-4"
>
Location
</th>
<th
scope="col"
class="px-6 py-4"
>
Start Date
</th>
<th
scope="col"
class="px-6 py-4"
>
End Date
</th>
<th
scope="col"
class="px-6 py-4"
>
Action
</th>
</tr>
</thead>
<tbody>
<tr
v-for="(event, index) in events"
:key="index"
class="border-b border-neutral-200 dark:border-white/10"
>
<td
class="whitespace-nowrap px-6 py-4"
>
{{ index + 1 }}
</td>
<td
class="whitespace-nowrap px-6 py-4"
>
{{ event.name }}
</td>
<td
class="whitespace-nowrap px-6 py-4"
>
{{ event.location }}
</td>
<td
class="whitespace-nowrap px-6 py-4"
>
{{
formatDate(
event.from_datetime
)
}}
</td>
<td
class="whitespace-nowrap px-6 py-4"
>
{{
formatDate(
event.to_datetime
)
}}
</td>
<td
class="whitespace-nowrap px-6 py-4"
>
<Link
:href="
route(
'event.show',
[event.id]
)
"
class="p-3 rounded my-auto text-white bg-green-600"
>
View
</Link>
<Link
:href="
route(
'event.edit',
{ id: event.id }
)
"
class="ml-2 p-3 rounded my-auto text-white bg-blue-500"
>
Edit
</Link>
<DangerButton
class="ml-2 py-3 rounded my-auto text-white bg-red-500"
@click="
deleteEvent(
event.id
)
"
>
Delete
</DangerButton>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
</template>
- Backend code to view all the events
/**
* Show the all the event details
*/
public function index()
{
return Inertia::render('EventManagement/Index', [
'events' => Event::get()
]);
}
Step 4: Create a view page to show the event details. Create View.vue
component and add the code below.
<script setup>
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
import moment from "moment-js";
import { Link } from "@inertiajs/vue3";
const props = defineProps({
event: Object,
});
const formatDate = (date) => {
return moment(date).format("MM/DD/YYYY hh:mm");
};
</script>
<template>
<Head :title="props.event.name" />
<AuthenticatedLayout>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<Link
class="py-3 px-5 m-2 rounded bg-blue-600 text-white float-end"
:href="route('event.index')"
>Back</Link
>
<div class="p-12 px-3 m-auto rounded-lg">
<div class="mt-12 bg-white py-5 px-3 rounded-lg">
<h1 class="text-2xl font-bold">
{{ props.event.name }}
</h1>
<div>
{{ props.event.location }}
</div>
<div class="text-sm">
{{ formatDate(props.event.from_datetime) }} -
{{ formatDate(props.event.to_datetime) }}
</div>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
</template>
Step 5: Create an edit page to edit the event. Create Edit.vue
component and add the code below.
<script setup>
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
import { Head, useForm, usePage } from "@inertiajs/vue3";
import VueDatePicker from "@vuepic/vue-datepicker";
import PrimaryButton from "@/Components/PrimaryButton.vue";
const props = defineProps(["event"]);
const form = useForm({
id: props.event.id,
name: props.event.name,
location: props.event.location,
startDate: props.event.from_datetime,
endDate: props.event.to_datetime,
});
const update = () => {
form.put(route("event.update", props.event.id));
};
</script>
<template>
<Head title="Event Management" />
<AuthenticatedLayout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Edit Event
</h2>
</template>
<div class="p-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<form @submit.prevent="update">
<div class="space-y-12 p-12">
<div class="border-b border-gray-900/10 pb-12">
<h2
class="text-base font-semibold leading-7 text-gray-900"
>
Event
</h2>
<p class="mt-1 text-sm leading-6 text-gray-600">
Update the event details here
</p>
<div
class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"
>
<div class="sm:col-span-3">
<label
for="name"
class="block text-sm font-medium leading-6 text-gray-900"
>Event name</label
>
<div class="mt-2">
<input
type="text"
v-model="form.name"
id="name"
autocomplete="event name"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div class="sm:col-span-3">
<label
for="location"
class="block text-sm font-medium leading-6 text-gray-900"
>Location</label
>
<div class="mt-2">
<input
type="text"
v-model="form.location"
id="location"
autocomplete="location"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div class="sm:col-span-3">
<label
for="start-date"
class="block text-sm font-medium leading-6 text-gray-900"
>Start Date</label
>
<VueDatePicker
v-model="form.startDate"
/>
</div>
<div class="sm:col-span-3">
<label
for="end-date"
class="block text-sm font-medium leading-6 text-gray-900"
>End date</label
>
<VueDatePicker v-model="form.endDate" />
</div>
</div>
</div>
<div
class="mt-6 flex items-center justify-end gap-x-6"
>
<button
type="button"
class="text-sm font-semibold leading-6 text-gray-900"
>
Cancel
</button>
<PrimaryButton
class="bg-indigo-800 hover:bg-blue-500"
>Save</PrimaryButton
>
</div>
</div>
</form>
</div>
</div>
</div>
</AuthenticatedLayout>
</template>
- Add this backend code for show create event page, show event, edit, update, and delete an event.
/**
* Show the form for creating a new event.
*/
public function create()
{
return Inertia::render('EventManagement/Create');
}
/**
* Show the event details
*/
public function show(Event $event)
{
return Inertia::render(
'EventManagement/View',
[
'event' => $event
]
);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Event $event)
{
return Inertia::render(
'EventManagement/Edit',
[
'event' => $event
]
);
}
/**
* Update the event
*/
public function update(Request $request, Event $event)
{
$params = $request->all();
$data = [
'name' => $params['name'],
'from_datetime' => $params['startDate'],
'to_datetime' => $params['endDate'],
'location' => $params['location'],
];
$event->update($data);
return redirect()->route('event.index');
}
/**
* Delete event
*/
public function delete(Event $event)
{
$event->delete();
return redirect()->back();
}
You can download the code from the github repository here.
Event Management Github
Happy Coding!!!
Happy Reading!! š¦ ā¤ļø
Top comments (1)
Hi! If I want to edit the resource in the same view of the index, like using a modal, how I can get the data?, I try with form.get but Inertia tells me that I need an Inertia Response, I understand that is using a redirect but I can use a simple JSON response? or do I need to change the process?