Frontend

laravel-livewire

Creates Livewire 3 reactive components with forms, tables, modals

Overview

The laravel-livewire agent creates reactive components using Livewire 3. It generates forms with real-time validation, data tables with sorting/filtering, modals, wizards, and handles component communication.

Responsibilities

  • Form Components - Create/edit forms with real-time validation
  • Data Tables - Searchable, sortable, paginated tables
  • Modal Components - Confirmation and form modals
  • Multi-step Wizards - Form wizards with step validation
  • Component Events - Inter-component communication
  • File Uploads - WithFileUploads integration

What It Creates

Component Location Purpose
PHP Class app/Livewire/ Component logic and state
Blade View resources/views/livewire/ Component template
Tests tests/Feature/Livewire/ Component tests

Generated Form Component

<?php

namespace App\Livewire;

use App\Models\Post;
use Livewire\Attributes\Rule;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Title('Create Post')]
class CreatePost extends Component
{
    #[Rule('required|min:3|max:255')]
    public string $title = '';

    #[Rule('required|min:10')]
    public string $content = '';

    #[Rule('nullable|exists:categories,id')]
    public ?int $category_id = null;

    public function save()
    {
        $validated = $this->validate();

        $post = Post::create([
            ...$validated,
            'user_id' => auth()->id(),
        ]);

        session()->flash('success', 'Post created successfully!');

        $this->redirect(route('posts.show', $post));
    }

    public function render()
    {
        return view('livewire.create-post', [
            'categories' => \App\Models\Category::all(),
        ]);
    }
}

Generated Data Table

<?php

namespace App\Livewire;

use App\Models\User;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

class UserTable extends Component
{
    use WithPagination;

    #[Url]
    public string $search = '';

    #[Url]
    public string $sortBy = 'created_at';

    #[Url]
    public string $sortDirection = 'desc';

    public function updatedSearch()
    {
        $this->resetPage();
    }

    public function sort(string $column)
    {
        if ($this->sortBy === $column) {
            $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
            $this->sortBy = $column;
            $this->sortDirection = 'asc';
        }
    }

    public function render()
    {
        $users = User::query()
            ->when($this->search, fn ($q) => $q->where('name', 'like', "%{$this->search}%")
                ->orWhere('email', 'like', "%{$this->search}%"))
            ->orderBy($this->sortBy, $this->sortDirection)
            ->paginate(15);

        return view('livewire.user-table', compact('users'));
    }
}

Component Communication

// Dispatching events
$this->dispatch('post-created', id: $post->id);

// Listening in another component
use Livewire\Attributes\On;

#[On('post-created')]
public function handlePostCreated(int $id): void
{
    $this->posts = Post::latest()->get();
}

// From JavaScript
Livewire.dispatch('post-created', { id: 1 });

Modal Example

<?php

namespace App\Livewire;

use App\Models\Post;
use Livewire\Component;

class DeletePostModal extends Component
{
    public bool $show = false;
    public ?Post $post = null;

    public function open(Post $post)
    {
        $this->post = $post;
        $this->show = true;
    }

    public function delete()
    {
        $this->authorize('delete', $this->post);

        $this->post->delete();

        $this->dispatch('post-deleted');
        $this->show = false;

        session()->flash('success', 'Post deleted.');
    }

    public function render()
    {
        return view('livewire.delete-post-modal');
    }
}

Invoked By Commands

Called By

Best Practices

  • Use wire:key - Always add keys to list items
  • Debounce inputs - Use wire:model.live.debounce.300ms for search
  • Computed properties - Use #[Computed] for derived data
  • Small components - Keep components focused on one task

Guardrails

The Livewire agent follows strict rules:

  • ALWAYS use wire:key for list iterations
  • ALWAYS authorize actions in component methods
  • ALWAYS use form validation attributes
  • NEVER store sensitive data in public properties
  • NEVER use N+1 queries in render methods

See Also