Laravel Livewire Tutorial: Step-by-Step Guide

·

·

Livewire brings reactive components to Laravel Blade. You write PHP classes and Blade templates while Livewire handles AJAX updates, validation, and DOM diffing—ideal for dashboards, wizards, and admin panels.

Installing Livewire

Install Livewire via Composer and include scripts in your layout. No separate build step is required for basic components.

Livewire 3 uses @livewireStyles and @livewireScripts directives or the @vite integration in modern Laravel apps.

Step 1: Require the Livewire package

Run composer require livewire/livewire. Publish config optionally with php artisan livewire:publish –config.

Verify installation by checking vendor/livewire/livewire and the Livewire service provider auto-discovery.

composer require livewire/livewire

Step 2: Add directives to the layout

In resources/views/layouts/app.blade.php add @livewireStyles in head and @livewireScripts before </body>.

For Livewire 3 with Volt and full-page components, use @livewire('component-name') in routes.

@livewireStyles
<!-- content -->
@livewireScripts

Step 3: Create your first component

Run php artisan make:livewire Counter. This creates app/Livewire/Counter.php and resources/views/livewire/counter.blade.php.

Embed with <livewire:counter /> or @livewire('counter') in any Blade view.

php artisan make:livewire Counter

Step 4: Render on a route

Return a view containing the component from a route or use Route::get('/counter', Counter::class) for full-page components.

Full-page routing keeps URLs clean for admin tools built entirely in Livewire.

Route::get('/counter', Counter::class);

Properties, Actions, and Forms

Public properties on Livewire components are reactive. wire:model binds inputs to properties with automatic server sync.

Call public methods from the template with wire:click. Validation uses the same rules as HTTP controllers.

Step 1: Define reactive properties

In Counter.php set public int $count = 0. Increment with a public function increment() { $this->count++; }.

Bind the button: <button wire:click="increment">+</button>. Livewire re-renders only the changed DOM nodes.

public int $count = 0;

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

Step 2: Bind forms with wire:model

Use wire:model="email" on inputs. Add wire:model.live for instant updates or .blur for on-blur sync.

Large forms benefit from wire:model.defer to batch updates on submit instead of every keystroke.

<input type="text" wire:model="email">

Step 3: Validate inside the component

Call $this->validate(['email' => 'required|email']) in save() or use rules() method returning validation rules.

Display errors with @error('email') like standard Blade forms. Validation runs server-side on every action.

protected function rules(): array
{
    return ['email' => 'required|email'];
}

Step 4: Flash messages and redirects

Use session()->flash('status', 'Saved!') then render in the template. Redirect with return $this->redirect('/posts').

return $this->redirectRoute('posts.index') after create forms for PRG pattern compliance.

$this->redirectRoute('posts.index');

Advanced Livewire Patterns

Pagination, file uploads, and nested components scale Livewire to complex interfaces.

Use wire:loading directives for UX feedback while server actions run.

Step 1: Paginate Eloquent results

Use WithPagination trait and paginate() in render(): Post::paginate(10). Links work with wire:click preserved.

Theme pagination views to match your design. Livewire handles query string state automatically.

use LivewireWithPagination;

public function render()
{
    return view('livewire.post-list', [
        'posts' => Post::paginate(10),
    ]);
}

Step 2: Upload files with WithFileUploads

Add use WithFileUploads and public $photo. Validate and store in save() using $this->photo->store('photos', 'public').

Show progress with wire:loading on the submit button. Temporary preview uses $this->photo->temporaryUrl().

use LivewireWithFileUploads;

public $photo;

Step 3: Emit events between components

Dispatch events with $this->dispatch('post-created') and listen via #[On('post-created')] attribute on other components.

Event bus decouples modals, notifications, and list refresh logic across the page.

$this->dispatch('post-created');

Step 4: Test Livewire components

Use Livewire::test(Counter::class)->set('count', 5)->call('increment')->assertSet('count', 6).

Feature tests exercise real HTTP while Livewire::test isolates component logic quickly.

Livewire::test(Counter::class)
    ->call('increment')
    ->assertSet('count', 1);

Aadyanex builds production-ready Laravel applications with clean architecture, secure APIs, and long-term support.