Skip to main content

Documentation Index

Fetch the complete documentation index at: https://kawax.biz/llms.txt

Use this file to discover all available pages before exploring further.

What is Livewire?

Before Livewire, building dynamic UIs in a Laravel application meant reaching for Vue.js, React, or writing AJAX requests by hand. Livewire removes that requirement. Livewire is a Laravel package that lets you build reactive, interactive components entirely in PHP and Blade. Real-time form validation, live search, counters, and modals — everything that previously needed JavaScript can now be written in PHP.
Livewire 4 requires Laravel 10 or higher and PHP 8.1 or higher.

How it works

A Livewire component is a PHP class combined with a Blade template. When a user clicks a button or types in an input, Livewire sends an AJAX request in the background, runs the PHP logic, and updates only the changed parts of the page. You write pure PHP — Livewire handles the rest.

Installation

Run the following command in your Laravel project root:
composer require livewire/livewire
Laravel’s package auto-discovery takes care of registration. No additional configuration is needed.

Create a layout file

If you plan to use Livewire as full-page components, you need a layout file. Generate one with Artisan:
php artisan livewire:layout
This creates resources/views/layouts/app.blade.php:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>{{ $title ?? config('app.name') }}</title>

        @vite(['resources/css/app.css', 'resources/js/app.js'])

        @livewireStyles
    </head>
    <body>
        {{ $slot }}

        @livewireScripts
    </body>
</html>
@livewireStyles and @livewireScripts automatically inject Livewire and Alpine.js assets.

Your first component

Generate a component using Artisan. Let’s build a simple counter:
php artisan make:livewire Counter
This creates a single-file component at resources/views/livewire/counter.blade.php. Edit it to look like this:
<?php

use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }

    public function decrement(): void
    {
        $this->count--;
    }
};
?>

<div>
    <h1>Count: {{ $count }}</h1>

    <button wire:click="increment">+1</button>
    <button wire:click="decrement">-1</button>
</div>
Embed the component in any Blade template:
<livewire:counter />
Every button click updates the count without a page reload. wire:click wires a DOM event directly to a PHP method — no JavaScript required on your end.

Properties and actions

Properties — wire:model

The wire:model directive binds an input element to a component property bidirectionally.
<?php

use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';
};
?>

<div>
    <input type="text" wire:model="name" placeholder="Name">
    <input type="email" wire:model="email" placeholder="Email">

    <p>Hello, {{ $name }} ({{ $email }})</p>
</div>
By default, wire:model syncs on form actions (such as submit). Add modifiers to control sync timing:
SyntaxBehavior
wire:modelSyncs only on action (default)
wire:model.liveSends a request on every keystroke
wire:model.blurSyncs when the input loses focus (no extra request)
wire:model.live.blurSends a request when focus leaves the input

Actions — wire:click and wire:submit

wire:click maps click events to PHP methods. wire:submit maps form submissions.
<?php

use Livewire\Component;
use App\Models\Task;

new class extends Component {
    public string $taskName = '';

    public function addTask(): void
    {
        Task::create(['name' => $this->taskName]);
        $this->taskName = '';
    }

    public function render()
    {
        return $this->view([
            'tasks' => Task::latest()->get(),
        ]);
    }
};
?>

<div>
    <form wire:submit="addTask">
        <input type="text" wire:model="taskName" placeholder="Task name">
        <button type="submit">Add</button>
    </form>

    <ul>
        @foreach ($tasks as $task)
            <li>{{ $task->name }}</li>
        @endforeach
    </ul>
</div>

Real-time validation

Livewire 4 lets you attach validation rules directly to properties using the #[Validate] attribute.
<?php

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

new class extends Component {
    #[Validate('required|min:3')]
    public string $title = '';

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

    public function save(): void
    {
        $this->validate();

        Post::create([
            'title' => $this->title,
            'content' => $this->content,
        ]);

        $this->reset(['title', 'content']);

        session()->flash('message', 'Post saved.');
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <div>
            <input type="text" wire:model.live.blur="title" placeholder="Title">
            @error('title') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <div>
            <textarea wire:model.live.blur="content" placeholder="Content"></textarea>
            @error('content') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <button type="submit">Save</button>
    </form>
</div>
$this->validate() validates all properties at once on form submission. Using it alongside #[Validate] attribute-level validation gives you a two-step approach: per-field validation on blur, and full validation on submit.
Pair wire:model.live.blur with #[Validate] to display error messages the moment a user leaves an invalid input — without a page reload.

Lifecycle hooks

Livewire components expose lifecycle hooks you can use to run code at specific points:
HookWhen it runs
mount()When the component is first initialized (once only)
boot()At the start of every request (initial and subsequent)
updating($property, $value)Before a property is updated
updated($property)After a property is updated
rendering()Before the view renders
rendered()After the view renders
dehydrate()At the end of every request

mount() — initialization

Use mount() to initialize the component, similar to a constructor.
<?php

use Illuminate\Support\Facades\Auth;
use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';

    public function mount(): void
    {
        $this->name = Auth::user()->name;
        $this->email = Auth::user()->email;
    }
};
?>

<div>
    <p>Name: {{ $name }}</p>
    <p>Email: {{ $email }}</p>
</div>

updated() — react to property changes

Use updated() to run logic after a property changes. Scope it to a specific property by including the property name in the method name.
<?php

use Livewire\Component;

new class extends Component {
    public string $username = '';

    public function updatedUsername(): void
    {
        $this->username = strtolower($this->username);
    }
};
?>

<div>
    <input type="text" wire:model.live="username">
    <p>Username: {{ $username }}</p>
</div>
Every keystroke automatically converts the input to lowercase.

Integration with Laravel

Eloquent models as properties

Livewire can hold Eloquent model instances directly as component properties.
<?php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\User;

new class extends Component {
    public User $user;

    public function mount(User $user): void
    {
        $this->user = $user;
    }

    #[Validate('required|min:2')]
    public string $name = '';

    public function save(): void
    {
        $this->validate();
        $this->user->update(['name' => $this->name]);
        session()->flash('message', 'Profile updated.');
    }

    public function render()
    {
        return $this->view();
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <input type="text" wire:model="name" placeholder="Name">
        @error('name') <span style="color: red;">{{ $message }}</span> @enderror
        <button type="submit">Update</button>
    </form>
</div>

Form objects

For complex forms, extract form state into a dedicated Form Object to keep your component lean.
php artisan livewire:form PostForm
namespace App\Livewire\Forms;

use Livewire\Attributes\Validate;
use Livewire\Form;
use App\Models\Post;

class PostForm extends Form
{
    #[Validate('required|min:3')]
    public string $title = '';

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

    public function store(): void
    {
        Post::create($this->only(['title', 'content']));
    }
}
Use the form object in a component:
<?php

use App\Livewire\Forms\PostForm;
use Livewire\Component;

new class extends Component {
    public PostForm $form;

    public function save(): void
    {
        $this->form->validate();
        $this->form->store();
        $this->form->reset();
        session()->flash('message', 'Post created.');
    }
};
?>

<div>
    <form wire:submit="save">
        <input type="text" wire:model="form.title" placeholder="Title">
        @error('form.title') <span style="color: red;">{{ $message }}</span> @enderror

        <textarea wire:model="form.content" placeholder="Content"></textarea>
        @error('form.content') <span style="color: red;">{{ $message }}</span> @enderror

        <button type="submit">Publish</button>
    </form>
</div>

When to use Livewire

Use caseWhat Livewire handles well
Form handlingReal-time validation, error display
Data tablesLive search, sorting, pagination
Toggles and countersUI updates without page reloads
Admin panelsCRUD directly against Eloquent
Multi-step wizardsStep management in pure PHP
If you already know Blade, you can start using Livewire today. There is no JavaScript framework to learn.
For experiences that require SPA-level interactivity with a full JavaScript UI framework, Inertia.js is a better fit. But for forms, admin panels, and data tables, Livewire often results in simpler, more maintainable code. Start with a single small component and expand from there.

Livewire documentation

Full coverage of file uploads, pagination, testing, Alpine.js integration, and more.
Last modified on April 25, 2026