Certainly! This issue comes up frequently when working with Laravel Precognition + Inertia with Vue. The main problem is that Laravel's Precognitive validation depends on the Precognition request header and sending form data in the format expected by Laravel, but Inertia's <Form/> component doesn't handle Precognition out of the box.
Key Point
To trigger a Precognitive request, the validate() method must send the request with the proper Precognition header, and form data must be included. Otherwise, the back-end route will always succeed with a 204 No Content because Laravel believes the request is just a "ping" for the route's existence.
Solution
1. Modify Your <input> Tag
Your <input> currently lacks v-model. Thus, its value doesn't get tracked and sent with the validate() call.
Change:
<input name="email" value="123">
To:
<input v-model="form.email" name="email" />
2. Use the Form Helper Correctly
Define your form data:
<script setup>
import { Form } from '@inertiajs/vue3';
const form = Form({
email: '', // or set a default if you want
});
</script>
3. Use the Correct <Form> Syntax
Put :form="form" on the <Form> tag:
<Form method="post" :form="form" #default="{ errors, validate }">
<input v-model="form.email" name="email" />
<p>{{ errors.email }}</p>
<a @click.prevent="validate()">Validate</a><br>
<button>Submit</button>
</Form>
Why? The
validate()method sends the data informusing a POST request (with the appropriate Precognition header).
4. Make Sure the Middleware is Applied
Your route is correct:
Route::post('/', function (EmailRequest $request) { ... })
->middleware(HandlePrecognitiveRequests::class);
This is good!
5. Review the Validation Rule
You have:
'email' => 'email',
For stricter validation, add 'required':
'email' => ['required', 'email'],
6. Final Code Example
routes/web.php
use App\Http\Requests\EmailRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
use Illuminate\Support\Facades\Route;
Route::inertia('/', 'Welcome')->name('home');
Route::post('/', function (EmailRequest $request) {
// Your logic here
})->middleware(HandlePrecognitiveRequests::class);
app/Http/Requests/EmailRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class EmailRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'email' => ['required', 'email'],
];
}
}
resources/js/Pages/Welcome.vue
<script setup>
import { Form } from '@inertiajs/vue3';
const form = Form({
email: '',
});
</script>
<template>
<Form method="post" :form="form" #default="{ errors, validate }">
<input v-model="form.email" name="email" />
<p>{{ errors.email }}</p>
<a @click.prevent="validate()">Validate</a><br>
<button>Submit</button>
</Form>
</template>
Now, when you type an invalid email and click "Validate," the validate() method will send a precognitive request with form data and the expected header, and Laravel will respond with validation errors instead of always a 204.
Summary:
The previous code did not actually send the input value to the backend when using validate() (because it wasn't tracked in a reactive form object); thus, Laravel could not validate it, and always returned 204. By using a Form instance and binding the input with v-model, Inertia will send the data, and Laravel will properly return validation errors via Precognition.
Let me know if you have further questions!