In this short tutorial, we will see how to upload a file using Laravel 9 with Inertia and Vue 3. For this section, we will use the Vue 3 SFCs method with <script setup>
.
Create a PostController and store data with an image.
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'description' => 'required',
'image' => 'nullable|image|mimes:jpg,png,jpeg,gif,svg|max:2048',
]);
$image_path = '';
if ($request->hasFile('image')) {
$image_path = $request->file('image')->store('image', 'public');
}
Post::create([
'name' => $request->name,
'description' => $request->description,
'image' => $image_path
]);
sleep(1);
return redirect()->route('posts.index')->with('message', 'Post Created Successfully');
}
Create posts routes.
Route::resource('posts',PostController::class);
Posts/Create.vue
<script setup>
import BreezeAuthenticatedLayout from "@/Layouts/Authenticated.vue";
import { Head } from "@inertiajs/inertia-vue3";
import BreezeButton from "@/Components/Button.vue";
import { Link } from "@inertiajs/inertia-vue3";
import { useForm } from "@inertiajs/inertia-vue3";
const form = useForm({
name: "",
image: "",
description: "",
});
const submit = () => {
form.post(route("posts.store"), {
forceFormData: true,
});
};
</script>
<template>
<Head title="Posts Create" />
<BreezeAuthenticatedLayout>
<template #header>
<h2 class="text-xl font-semibold leading-tight text-gray-800">
Post Create
</h2>
</template>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<form @submit.prevent="submit">
<div class="mb-6">
<label
for="Name"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>Name</label
>
<input
type="text"
v-model="form.name"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder=""
/>
<div
v-if="form.errors.name"
class="text-sm text-red-600"
>
{{ form.errors.name }}
</div>
</div>
<div class="mb-4">
<input
type="file"
name="image"
@input="form.image = $event.target.files[0]"
/>
<div
v-if="form.errors.image"
class="text-sm text-red-600"
>
{{ form.errors.image }}
</div>
</div>
<div class="mb-6">
<label
for="slug"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>description</label
>
<textarea
type="text"
v-model="form.description"
name="description"
id=""
cols="30"
rows="10"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
></textarea>
<div
v-if="form.errors.description"
class="text-sm text-red-600"
>
{{ form.errors.description }}
</div>
</div>
<button
type="submit"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
:disabled="form.processing"
:class="{ 'opacity-25': form.processing }"
>
Submit
</button>
</form>
</div>
</div>
</div>
</div>
</BreezeAuthenticatedLayout>
</template>