Laravel Precognition is a powerful feature that allows developers to provide real-time form validation without duplicating validation rules on the frontend. By anticipating the outcome of future HTTP requests, Precognition streamlines the validation process and significantly improves user experience. In this post, we'll explore how to implement Precognition and showcase some practical examples.
Getting Started with Precognition
To use Precognition, you first need to add the HandlePrecognitiveRequests
middleware to your route:
use App\Http\Requests\CreateUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (CreateUserRequest $request) {
// ...
})->middleware([HandlePrecognitiveRequests::class]);
Implementing Live Validation
Let's look at an example using Vue.js and Inertia. First, install the necessary package:
npm install laravel-precognition-vue
Now, create a form component:
<script setup>
import { useForm } from 'laravel-precognition-vue';
const form = useForm('post', '/users', {
name: '',
email: '',
password: '',
});
const submit = () => form.submit();
</script>
<template>
<form @submit.prevent="submit">
<input v-model="form.name" @change="form.validate('name')" />
<div v-if="form.invalid('name')">{{ form.errors.name }}</div>
<input type="email" v-model="form.email" @change="form.validate('email')" />
<div v-if="form.invalid('email')">{{ form.errors.email }}</div>
<input type="password" v-model="form.password" @change="form.validate('password')" />
<div v-if="form.invalid('password')">{{ form.errors.password }}</div>
<button :disabled="form.processing">Create User</button>
</form>
</template>
This setup provides real-time validation as the user types, using your server-side validation rules.
Suggested Usages
Multi-step Forms: Use Precognition to validate each step before allowing the user to proceed.
<script setup> import { useForm } from 'laravel-precognition-vue'; const form = useForm('post', '/registration', { step: 1, name: '', email: '', // ... other fields }); const nextStep = async () => { await form.validate(['name', 'email']); if (!form.hasErrors()) { form.step++; } }; </script>
Dynamic Form Fields: Validate fields that depend on other inputs.
<script setup> import { useForm, watch } from 'laravel-precognition-vue'; const form = useForm('post', '/order', { product_id: null, quantity: 1, }); watch(() => form.product_id, () => { form.validate('quantity'); }); </script>
Debounced Validation: Implement debounced validation for fields like usernames or email addresses.
<script setup> import { useForm } from 'laravel-precognition-vue'; import { debounce } from 'lodash'; const form = useForm('post', '/register', { username: '', }); const debouncedValidate = debounce(() => form.validate('username'), 300); </script> <template> <input v-model="form.username" @input="debouncedValidate" /> </template>
File Upload Validation: Use Precognition to validate file uploads before sending the entire form.
<script setup> import { useForm } from 'laravel-precognition-vue'; const form = useForm('post', '/profile', { avatar: null, }); const validateFile = (event) => { form.avatar = event.target.files[0]; form.validate('avatar'); }; </script> <template> <input type="file" @change="validateFile" /> <div v-if="form.invalid('avatar')">{{ form.errors.avatar }}</div> </template>
Best Practices
Keep Backend Validation: Always maintain server-side validation as the ultimate authority.
Handle Network Errors: Provide feedback for network issues during validation.
Progressive Enhancement: Ensure your forms work without JavaScript as a fallback.
Performance Considerations: Be mindful of the number of requests made, especially for high-traffic applications.
Laravel Precognition offers a powerful way to enhance user experience by providing immediate feedback without sacrificing the security and reliability of server-side validation. By implementing Precognition in your Laravel applications, you can create more responsive and user-friendly forms while maintaining a single source of truth for your validation rules.