Skip to content
Steven Roland

Enhancing User Experience with Laravel Precognition

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.

Support My Work

If you enjoy my content, consider supporting me through Buy Me a Coffee or GitHub Sponsors.

Buy Me A Coffee
or

More posts

The Art of Leaving: Growing Roots Before Taking Flight

Inspired by John Green's quote, this post explores the paradox of leaving: to truly appreciate departure, we must first establish deep connections. It encourages readers to grow roots while maintaining the courage to leave for personal growth.

Building a Dynamic Tabs Component with Alpine.js

Learn to create an interactive and accessible tabs component using Alpine.js. This tutorial covers basic implementation, styling enhancements, accessibility features, and keyboard navigation. Build a user-friendly tabs interface with minimal JavaScript.