Skip to content

Commit ad7570a

Browse files
Merge pull request #173 from laravel/inertia-form-component
Migrate `useForm` to new Inertia `Form` component
2 parents e6cd4de + fbcf149 commit ad7570a

File tree

11 files changed

+626
-1070
lines changed

11 files changed

+626
-1070
lines changed

package-lock.json

Lines changed: 482 additions & 843 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"vue-tsc": "^2.2.4"
2424
},
2525
"dependencies": {
26-
"@inertiajs/vue3": "^2.0.0",
26+
"@inertiajs/vue3": "^2.1.0",
2727
"@tailwindcss/vite": "^4.1.11",
2828
"@vitejs/plugin-vue": "^6.0.0",
2929
"@vueuse/core": "^12.8.2",

resources/js/components/DeleteUser.vue

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { useForm } from '@inertiajs/vue3';
2+
import { Form } from '@inertiajs/vue3';
33
import { ref } from 'vue';
44
55
// Components
@@ -20,32 +20,12 @@ import { Input } from '@/components/ui/input';
2020
import { Label } from '@/components/ui/label';
2121
2222
const passwordInput = ref<HTMLInputElement | null>(null);
23-
24-
const form = useForm({
25-
password: '',
26-
});
27-
28-
const deleteUser = (e: Event) => {
29-
e.preventDefault();
30-
31-
form.delete(route('profile.destroy'), {
32-
preserveScroll: true,
33-
onSuccess: () => closeModal(),
34-
onError: () => passwordInput.value?.focus(),
35-
onFinish: () => form.reset(),
36-
});
37-
};
38-
39-
const closeModal = () => {
40-
form.clearErrors();
41-
form.reset();
42-
};
4323
</script>
4424

4525
<template>
4626
<div class="space-y-6">
4727
<HeadingSmall title="Delete account" description="Delete your account and all of its resources" />
48-
<div class="space-y-4 rounded-lg border border-red-100 bg-red-50 p-4 dark:border-red-200/10 dark:bg-red-700/10">
28+
<div class="p-4 space-y-4 border border-red-100 rounded-lg bg-red-50 dark:border-red-200/10 dark:bg-red-700/10">
4929
<div class="relative space-y-0.5 text-red-600 dark:text-red-100">
5030
<p class="font-medium">Warning</p>
5131
<p class="text-sm">Please proceed with caution, this cannot be undone.</p>
@@ -55,7 +35,17 @@ const closeModal = () => {
5535
<Button variant="destructive">Delete account</Button>
5636
</DialogTrigger>
5737
<DialogContent>
58-
<form method="POST" class="space-y-6" @submit="deleteUser">
38+
<Form
39+
method="delete"
40+
:action="route('profile.destroy')"
41+
reset-on-success
42+
@error="() => passwordInput?.focus()"
43+
:options="{
44+
preserveScroll: true,
45+
}"
46+
class="space-y-6"
47+
v-slot="{ errors, processing, reset, clearErrors }"
48+
>
5949
<DialogHeader class="space-y-3">
6050
<DialogTitle>Are you sure you want to delete your account?</DialogTitle>
6151
<DialogDescription>
@@ -66,18 +56,28 @@ const closeModal = () => {
6656

6757
<div class="grid gap-2">
6858
<Label for="password" class="sr-only">Password</Label>
69-
<Input id="password" type="password" name="password" ref="passwordInput" v-model="form.password" placeholder="Password" />
70-
<InputError :message="form.errors.password" />
59+
<Input id="password" type="password" name="password" ref="passwordInput" placeholder="Password" />
60+
<InputError :message="errors.password" />
7161
</div>
7262

7363
<DialogFooter class="gap-2">
7464
<DialogClose as-child>
75-
<Button variant="secondary" @click="closeModal"> Cancel </Button>
65+
<Button
66+
variant="secondary"
67+
@click="
68+
() => {
69+
clearErrors();
70+
reset();
71+
}
72+
"
73+
>
74+
Cancel
75+
</Button>
7676
</DialogClose>
7777

78-
<Button type="submit" variant="destructive" :disabled="form.processing"> Delete account </Button>
78+
<Button type="submit" variant="destructive" :disabled="processing"> Delete account </Button>
7979
</DialogFooter>
80-
</form>
80+
</Form>
8181
</DialogContent>
8282
</Dialog>
8383
</div>

resources/js/pages/auth/ConfirmPassword.vue

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,38 @@ import { Button } from '@/components/ui/button';
44
import { Input } from '@/components/ui/input';
55
import { Label } from '@/components/ui/label';
66
import AuthLayout from '@/layouts/AuthLayout.vue';
7-
import { Head, useForm } from '@inertiajs/vue3';
7+
import { Form, Head } from '@inertiajs/vue3';
88
import { LoaderCircle } from 'lucide-vue-next';
9-
10-
const form = useForm({
11-
password: '',
12-
});
13-
14-
const submit = () => {
15-
form.post(route('password.confirm'), {
16-
onFinish: () => {
17-
form.reset();
18-
},
19-
});
20-
};
219
</script>
2210

2311
<template>
2412
<AuthLayout title="Confirm your password" description="This is a secure area of the application. Please confirm your password before continuing.">
2513
<Head title="Confirm password" />
2614

27-
<form method="POST" @submit.prevent="submit">
15+
<Form method="post" :action="route('password.confirm')" reset-on-success v-slot="{ errors, processing }">
2816
<div class="space-y-6">
2917
<div class="grid gap-2">
3018
<Label htmlFor="password">Password</Label>
3119
<Input
3220
id="password"
3321
type="password"
34-
class="mt-1 block w-full"
35-
v-model="form.password"
22+
name="password"
23+
class="block w-full mt-1"
3624
required
3725
autocomplete="current-password"
3826
autofocus
3927
/>
4028

41-
<InputError :message="form.errors.password" />
29+
<InputError :message="errors.password" />
4230
</div>
4331

4432
<div class="flex items-center">
45-
<Button class="w-full" :disabled="form.processing">
46-
<LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
33+
<Button class="w-full" :disabled="processing">
34+
<LoaderCircle v-if="processing" class="w-4 h-4 animate-spin" />
4735
Confirm Password
4836
</Button>
4937
</div>
5038
</div>
51-
</form>
39+
</Form>
5240
</AuthLayout>
5341
</template>

resources/js/pages/auth/ForgotPassword.vue

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,12 @@ import { Button } from '@/components/ui/button';
55
import { Input } from '@/components/ui/input';
66
import { Label } from '@/components/ui/label';
77
import AuthLayout from '@/layouts/AuthLayout.vue';
8-
import { Head, useForm } from '@inertiajs/vue3';
8+
import { Form, Head } from '@inertiajs/vue3';
99
import { LoaderCircle } from 'lucide-vue-next';
1010
1111
defineProps<{
1212
status?: string;
1313
}>();
14-
15-
const form = useForm({
16-
email: '',
17-
});
18-
19-
const submit = () => {
20-
form.post(route('password.email'));
21-
};
2214
</script>
2315

2416
<template>
@@ -30,20 +22,20 @@ const submit = () => {
3022
</div>
3123

3224
<div class="space-y-6">
33-
<form method="POST" @submit.prevent="submit">
25+
<Form method="post" :action="route('password.email')" v-slot="{ errors, processing }">
3426
<div class="grid gap-2">
3527
<Label for="email">Email address</Label>
36-
<Input id="email" type="email" name="email" autocomplete="off" v-model="form.email" autofocus placeholder="email@example.com" />
37-
<InputError :message="form.errors.email" />
28+
<Input id="email" type="email" name="email" autocomplete="off" autofocus placeholder="email@example.com" />
29+
<InputError :message="errors.email" />
3830
</div>
3931

4032
<div class="my-6 flex items-center justify-start">
41-
<Button class="w-full" :disabled="form.processing">
42-
<LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
33+
<Button class="w-full" :disabled="processing">
34+
<LoaderCircle v-if="processing" class="h-4 w-4 animate-spin" />
4335
Email password reset link
4436
</Button>
4537
</div>
46-
</form>
38+
</Form>
4739

4840
<div class="space-x-1 text-center text-sm text-muted-foreground">
4941
<span>Or, return to</span>

resources/js/pages/auth/Login.vue

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,50 +6,38 @@ import { Checkbox } from '@/components/ui/checkbox';
66
import { Input } from '@/components/ui/input';
77
import { Label } from '@/components/ui/label';
88
import AuthBase from '@/layouts/AuthLayout.vue';
9-
import { Head, useForm } from '@inertiajs/vue3';
9+
import { Form, Head } from '@inertiajs/vue3';
1010
import { LoaderCircle } from 'lucide-vue-next';
1111
1212
defineProps<{
1313
status?: string;
1414
canResetPassword: boolean;
1515
}>();
16-
17-
const form = useForm({
18-
email: '',
19-
password: '',
20-
remember: false,
21-
});
22-
23-
const submit = () => {
24-
form.post(route('login'), {
25-
onFinish: () => form.reset('password'),
26-
});
27-
};
2816
</script>
2917

3018
<template>
3119
<AuthBase title="Log in to your account" description="Enter your email and password below to log in">
3220
<Head title="Log in" />
3321

34-
<div v-if="status" class="mb-4 text-center text-sm font-medium text-green-600">
22+
<div v-if="status" class="mb-4 text-sm font-medium text-center text-green-600">
3523
{{ status }}
3624
</div>
3725

38-
<form method="POST" @submit.prevent="submit" class="flex flex-col gap-6">
26+
<Form method="post" :action="route('login')" :reset-on-success="['password']" v-slot="{ errors, processing }" class="flex flex-col gap-6">
3927
<div class="grid gap-6">
4028
<div class="grid gap-2">
4129
<Label for="email">Email address</Label>
4230
<Input
4331
id="email"
4432
type="email"
33+
name="email"
4534
required
4635
autofocus
4736
:tabindex="1"
4837
autocomplete="email"
49-
v-model="form.email"
5038
placeholder="email@example.com"
5139
/>
52-
<InputError :message="form.errors.email" />
40+
<InputError :message="errors.email" />
5341
</div>
5442

5543
<div class="grid gap-2">
@@ -62,32 +50,32 @@ const submit = () => {
6250
<Input
6351
id="password"
6452
type="password"
53+
name="password"
6554
required
6655
:tabindex="2"
6756
autocomplete="current-password"
68-
v-model="form.password"
6957
placeholder="Password"
7058
/>
71-
<InputError :message="form.errors.password" />
59+
<InputError :message="errors.password" />
7260
</div>
7361

7462
<div class="flex items-center justify-between">
7563
<Label for="remember" class="flex items-center space-x-3">
76-
<Checkbox id="remember" v-model="form.remember" :tabindex="3" />
64+
<Checkbox id="remember" name="remember" :tabindex="3" />
7765
<span>Remember me</span>
7866
</Label>
7967
</div>
8068

81-
<Button type="submit" class="mt-4 w-full" :tabindex="4" :disabled="form.processing">
82-
<LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
69+
<Button type="submit" class="w-full mt-4" :tabindex="4" :disabled="processing">
70+
<LoaderCircle v-if="processing" class="w-4 h-4 animate-spin" />
8371
Log in
8472
</Button>
8573
</div>
8674

87-
<div class="text-center text-sm text-muted-foreground">
75+
<div class="text-sm text-center text-muted-foreground">
8876
Don't have an account?
8977
<TextLink :href="route('register')" :tabindex="5">Sign up</TextLink>
9078
</div>
91-
</form>
79+
</Form>
9280
</AuthBase>
9381
</template>

0 commit comments

Comments
 (0)