> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# ⚡ Getting started with Livewire 4 — reactive UIs without JavaScript

> Learn how to build interactive UIs without writing JavaScript using Laravel's first-party Livewire 4 package, from installation to practical code examples.

## What is Livewire?

Building a dynamic UI in Laravel used to mean combining a JavaScript framework like Vue.js or React, or writing AJAX requests yourself.

**Livewire** is a Laravel package that solves this problem. It lets you build reactive UIs using PHP and Blade only. Features that traditionally required JavaScript—real-time form validation, live search, counters, etc.—can all be implemented in PHP.

<Info>
  Livewire 4 works on Laravel 10 or later and PHP 8.1 or later. The current latest version is Livewire 4.
</Info>

### How it works

A Livewire component is a combination of a PHP class on the server and a Blade template. When a user clicks a button or types into a form, Livewire sends an AJAX request in the background, executes PHP, and applies only the changed portions to the page. You can write everything in PHP without worrying about this mechanism.

***

## Installation

Run the following command in the root of your Laravel application.

```shell theme={null}
composer require livewire/livewire
```

Laravel's package auto-discovery is enabled, so no additional configuration is required.

### Creating a layout file

If you use it as a full-page component, a layout file is needed. You can generate one with this Artisan command:

```shell theme={null}
php artisan livewire:layout
```

This generates `resources/views/layouts/app.blade.php`:

```blade theme={null}
<!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 load the Livewire and Alpine.js assets.

***

## Your first component

An Artisan command is provided to generate Livewire components. Let's build a simple counter.

```shell theme={null}
php artisan make:livewire Counter
```

This command creates a single-file component at `resources/views/components/⚡counter.blade.php`.

<Tip>
  The ⚡ in the filename makes Livewire components identifiable at a glance. It improves editor visibility. You can disable it in the configuration if you prefer.
</Tip>

Edit the generated file as follows.

```blade theme={null}
<?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 this component in a Blade template using the ordinary Blade component syntax.

```blade theme={null}
<livewire:counter />
```

Every button click updates the count without a page reload. `wire:click` calls a PHP method instead of running JavaScript.

***

## Properties and actions

### Properties — `wire:model`

The `wire:model` directive two-way binds an input element to a component property.

```blade theme={null}
<?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` only syncs with the server when an action (like a form submit) fires. If you want to sync on each keystroke, add the `.live` modifier.

| Syntax                 | Behavior                                |
| ---------------------- | --------------------------------------- |
| `wire:model`           | Sync only when an action runs (default) |
| `wire:model.live`      | Send a request on every input           |
| `wire:model.blur`      | Sync on blur (no request)               |
| `wire:model.live.blur` | Send a request on blur                  |

### Actions — `wire:click` and `wire:submit`

`wire:click` binds click events to methods, and `wire:submit` binds form submission events.

```blade theme={null}
<?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

In Livewire 4, the `#[Validate]` attribute lets you define validation rules directly on properties.

```blade theme={null}
<?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>
```

Properties annotated with `#[Validate]` run automatic validation on every update. Combined with `wire:model.live.blur`, you get a real-time validation experience where the error message appears the moment focus leaves the field.

<Info>
  `$this->validate()` validates all properties together on form submission. The recommended pattern is to combine automatic validation via `#[Validate]` with an explicit final validation.
</Info>

***

## Lifecycle hooks

Livewire components have several lifecycle hooks.

| Hook                          | Timing                                                 |
| ----------------------------- | ------------------------------------------------------ |
| `mount()`                     | When the component is first created (only once)        |
| `boot()`                      | At the start of every request (initial and subsequent) |
| `updating($property, $value)` | Just before a property updates                         |
| `updated($property)`          | Just after a property updates                          |
| `rendering()`                 | Before the view renders                                |
| `rendered()`                  | After the view renders                                 |
| `dehydrate()`                 | At the end of every request                            |

### `mount()` — initialization

Use `mount()` to initialize a component. It replaces the constructor.

```blade theme={null}
<?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()` — after property changes

If you want to run logic after a property updates, use `updated()`. To target a specific property, include it in the method name.

```blade theme={null}
<?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 is automatically converted to lowercase.

***

## Laravel integration

### Working with Eloquent models

Livewire can hold Eloquent models directly as properties.

```blade theme={null}
<?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

Extracting complex forms into form objects keeps components simple.

```shell theme={null}
php artisan livewire:form PostForm
```

```php theme={null}
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 from a component.

```blade theme={null}
<?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">Post</button>
    </form>
</div>
```

***

## Summary

Here's where Livewire is especially well-suited:

| Use case             | What Livewire enables                  |
| -------------------- | -------------------------------------- |
| Form handling        | Real-time validation and error display |
| Data lists           | Live search, sorting, and pagination   |
| Counters and toggles | UI updates without a page reload       |
| Admin panels         | CRUD via direct Eloquent integration   |
| Wizard-style forms   | Step management in PHP                 |

If you've used Blade before, you can start writing Livewire today. Its biggest strength is delivering interactive UIs without the learning curve of a JavaScript framework.

For SPA-level advanced interactions, Inertia.js is the better fit, but for forms, admin panels, and data tables, Livewire is often simpler to build. Try starting with one small component.

<Card title="Livewire official docs" icon="book-open" href="https://livewire.laravel.com/docs">
  See the official documentation for Livewire's full feature set (file uploads, pagination, testing, and more).
</Card>


## Related topics

- [Getting started with Svelte — the essentials for using it with Inertia × Laravel](/en/blog/svelte-introduction.md)
- [Knowledge required before starting Laravel](/en/true-tutorial.md)
- [Getting started with React — the essentials for using it with Inertia × Laravel](/en/blog/react-introduction.md)
- [Getting started with Vue.js — the essentials for using it with Inertia × Laravel](/en/blog/vue-introduction.md)
- [Frontend](/en/frontend.md)
