Cheatsheets / Livewire

Livewire Cheatsheet

Complete Livewire v3 reference. Hit Ctrl+P to print.

Artisan & Setup

php artisan make:livewire MyComponentGenerate component class + Blade view
php artisan make:livewire --test MyComponentGenerate component with Pest test file
php artisan make:livewire pages/DashboardGenerate in subdirectory (pages/dashboard.blade.php)
php artisan make:livewire --inline MyComponentGenerate component with inline view (no separate Blade)
php artisan livewire:publish --configPublish Livewire config to config/livewire.php
php artisan livewire:publish --assetsPublish Livewire JS assets
php artisan livewire:upgradeUpgrade v2 components to v3 syntax
@livewire('my-component')Mount a component in a Blade view
@livewire('my-component', ['param' => $value])Mount with initial parameters
<livewire:my-component />Mount using tag syntax
<livewire:my-component :param="$value" />Mount with parameter via tag syntax
<livewire:my-component key="unique-key" />Force fresh instance with key attribute
@livewireStylesInject Livewire CSS (place in )
@livewireScriptsInject Livewire JS (place before )

Component Class

use Livewire\Component;Import base component class
use Livewire\Attributes\Locked;Import #[Locked] attribute
use Livewire\Attributes\Computed;Import #[Computed] attribute
use Livewire\Attributes\Url;Import #[Url] query-string attribute
use Livewire\Attributes\Session;Import #[Session] attribute
use Livewire\Attributes\Modelable;Import #[Modelable] attribute
use Livewire\Attributes\On;Import #[On] event listener attribute
use Livewire\Attributes\Lazy;Import #[Lazy] lazy-load attribute
use Livewire\Attributes\Validate;Import #[Validate] attribute
class MyComponent extends ComponentDeclare a Livewire component
public string $name = '';Public string property (synced to template)
public int $count = 0;Public integer property
public bool $active = false;Public boolean property
public array $items = [];Public array property
public ?Model $post = null;Public Eloquent model property
#[Locked] public int $id;Prevent client from modifying property
#[Computed] public function posts()Cached computed property (accessed as $this->posts)
#[Url] public string $search = '';Sync property to URL query string
#[Url(as: 'q')] public string $search = '';Sync to query string with custom alias
#[Session] public string $tab = 'general';Persist property value in session
#[Modelable] public string $value = '';Allow parent to bind via wire:model
public function mount(int $id): voidRuns once on first render; receives component params
public function render(): ViewReturn the component's Blade view
public function boot(): voidRuns before every request (use for DI or setup)
public function booted(): voidRuns after boot() on every request

Actions

public function save(): voidPublic method callable from template
wire:click="save"Call action on click
wire:click="increment"Call increment() on click
wire:click="delete($item->id)"Call action with parameter
wire:click="delete({{ $item->id }})"Pass PHP-evaluated param to action
wire:click.prevent="submit"Call action and prevent default browser behavior
wire:click.stop="close"Call action and stop event propagation
wire:submit="save"Call action on form submit
wire:submit.prevent="save"Call action on submit, prevent page reload
wire:keydown.enter="save"Call action when Enter key is pressed
wire:keydown.escape="close"Call action when Escape key is pressed
wire:keydown.tab="next"Call action on Tab keydown
$this->redirect('/dashboard')Redirect to URL from action
$this->redirectRoute('dashboard')Redirect to named route from action
$this->redirectRoute('posts.show', $post)Redirect to named route with model
return $this->redirect('/')->with('status', 'Saved')Redirect with flash message
$this->dispatch('post-created', id: $post->id)Dispatch event from action
$this->dispatch('event')->to(OtherComponent::class)Dispatch to specific component class
$this->dispatch('event')->self()Dispatch only to self (same component)

Properties & Data Binding

wire:model="name"Bind input to property (deferred by default in v3)
wire:model.live="name"Update property on every input event
wire:model.live.debounce.500ms="search"Live binding with 500ms debounce
wire:model.live.debounce.300ms="query"Live binding with 300ms debounce
wire:model.blur="name"Update property when input loses focus
wire:model.lazy="name"Update property on change event
public int $age = 0PHP type hint auto-casts bound value to int
public bool $active = falsePHP type hint auto-casts bound value to bool
wire:model="address.street"Bind to nested array key
wire:model="todos.{{ $index }}.label"Bind to indexed array element
$wire.nameRead property value from Alpine.js
$wire.set('name', value)Set property value from Alpine.js
$wire.get('name')Get property value from Alpine.js
$wire.$watch('name', cb)Watch for property changes in Alpine.js

Events

#[On('post-created')] public function handlePost()Listen for event on method
#[On('post-created')] public function handle(int $id)Listener receiving event data
$this->dispatch('post-created')Dispatch event to all listeners
$this->dispatch('post-created', id: $post->id)Dispatch event with named data
$this->dispatch('post-created', data: ['id' => $post->id])Dispatch with data array
$this->dispatch('event')->to(OtherComponent::class)Target event to specific component class
$this->dispatch('event')->to('other-component')Target event to component by name
$this->dispatch('event')->self()Dispatch event only to current component
$this->dispatchTo('other-component', 'refresh')Dispatch to component by name (deprecated in v3; prefer ->to() chain)
$this->dispatch('browser-event')Dispatch Livewire event (received by components and JS via Livewire.on())
@post-created.window="handler"Listen for Livewire browser event in Alpine
Livewire.on('event-name', (data) => {})Listen to Livewire event in JavaScript (v3)
Livewire.dispatch('event', { id: 1 })Dispatch event from plain JavaScript

Lifecycle Hooks

mount()Runs once on initial render; receives component parameters
boot()Runs at the start of every component request
booted()Runs after boot() on every request
hydrate()Runs at start of each subsequent request (after mount)
dehydrate()Runs at end of every request before response is sent
updating($name, $value)Runs before any property is updated
updated($name, $value)Runs after any property is updated
updatingName($value)Runs before $name property is updated (camelCase)
updatedName($value)Runs after $name property is updated (camelCase)
updatingAddress($value, $key)Runs before nested array property update
rendering()Runs before render() is called
rendered($view)Runs after render() returns a view
exception($e, $stopPropagation)Handle component exception; call $stopPropagation() to suppress

Validation

#[Validate('required|min:3')] public string $nameInline validation rule on property
#[Validate('required|email')] public string $emailEmail validation rule on property
#[Validate(['name' => 'required|min:3', 'email' => 'email'])]Multi-field rules on class
#[Validate('required', message: 'Name is required')] public string $nameCustom validation message on property
$this->validate()Validate all properties with their rules
$this->validate(['name' => 'required'])Validate with ad-hoc rules
$this->validateOnly('name')Validate a single property (e.g. for real-time feedback)
$this->addError('name', 'Custom message')Manually add a validation error
$this->resetErrorBag()Clear all validation errors
$this->resetValidation('name')Clear validation error for one property
$errors->has('name')Check if a validation error exists in template
@error('name') {{ $message }} @enderrorRender validation error message in template
use Livewire\WithFileUploads;Add file upload support to component
public ?TemporaryUploadedFile $photo = null;Typed file upload property
#[Validate(['photo' => 'image|max:1024'])]Validate uploaded file (1 MB max)
<input type="file" wire:model="photo">File input bound to upload property
$this->photo->store(path: 'photos', disk: 'public')Store uploaded file to disk

wire: Directives

wire:clickTrigger action on click
wire:submitTrigger action on form submit
wire:modelTwo-way bind input to property (deferred)
wire:model.liveTwo-way bind with live updates on input
wire:model.blurTwo-way bind; updates on blur
wire:model.lazyTwo-way bind; updates on change
wire:model.live.debounce.XmsDebounce live updates (requires .live)
wire:keydownTrigger action on keydown
wire:keydown.enterTrigger action on Enter key
wire:keydown.escapeTrigger action on Escape key
wire:keyupTrigger action on keyup
wire:changeTrigger action on change event
wire:inputTrigger action on input event
wire:mouseenterTrigger action on mouseenter
wire:mouseleaveTrigger action on mouseleave
wire:focusTrigger action on focus
wire:blurTrigger action on blur
wire:loadingShow element while a request is in-flight
wire:loading.attr="disabled"Add attribute while loading
wire:loading.class="opacity-50"Add class while loading
wire:loading.removeRemove element while loading
wire:target="save"Scope loading state to a specific action
wire:dirtyShow element when property is modified but not yet saved
wire:dirty.class="border-yellow-500"Apply class when input is dirty
wire:dirty.remove.class="hidden"Remove class when input is dirty
wire:confirm="Are you sure?"Show browser confirm dialog before firing action
wire:navigateSPA-style navigation (no full page reload)
wire:navigate.hoverPrefetch page on hover then navigate on click
wire:transitionAnimate element changes with default transition
wire:pollRefresh component every 2s (default)
wire:poll.5sRefresh component every 5 seconds
wire:poll.750msRefresh component every 750ms
wire:poll.visibleOnly poll when element is visible in viewport
wire:offlineShow element when browser is offline
wire:offline.class="opacity-50"Apply class when browser is offline
wire:stream="output"Stream content into element from $this->stream()

Lazy Loading

#[Lazy]Attribute on component class to enable lazy loading
<livewire:my-component lazy />Enable lazy loading from template
<livewire:my-component :lazy="$condition" />Conditionally lazy-load component
public function placeholder(): ViewReturn a placeholder view shown before full render
return view('livewire.placeholders.spinner')Return spinner view as placeholder
<x-slot name="placeholder">...</x-slot>Inline placeholder using named slot
// mount() deferredmount() runs on lazy hydration request, not initial page load
Request fired after page loadFull component loads via separate background XHR
#[Lazy(isolate: true)]Isolate lazy requests so they run independently

Alpine.js Integration

$wireAlpine magic that gives access to the Livewire component
$wire.nameRead a Livewire property from Alpine
$wire.set('name', value)Set a Livewire property from Alpine
$wire.get('name')Get a Livewire property value from Alpine
$wire.call('methodName', ...args)Call a Livewire method from Alpine
$wire.methodName(args)Shorthand: call Livewire method from Alpine
$wire.commit()Force a Livewire network request from Alpine
$wire.$watch('name', cb)Watch a Livewire property for changes in Alpine
@entangle('open')Two-way Alpine ↔ Livewire property binding
@entangle('open').liveEntangle with immediate server sync
x-data="{ open: $wire.entangle('open') }"Entangle inside x-data object
Livewire.on('event', callback)Listen for Livewire events in plain JS
Livewire.dispatch('event', data)Dispatch Livewire event from plain JS
Livewire.hook('request', cb)Hook into Livewire lifecycle from JS
Livewire.start()Manually initialise Livewire (when not using auto-inject)
@this.nameLegacy v2 syntax; prefer $wire in v3

Testing

use Livewire\Livewire;Import the Livewire test helper
Livewire::test(MyComponent::class)Create a testable component instance
Livewire::test(MyComponent::class, ['id' => 1])Create component with initial parameters
->set('name', 'Alice')Set a property value
->call('save')Call an action method
->call('delete', $id)Call action with arguments
->assertSee('Alice')Assert text is present in rendered output
->assertDontSee('Error')Assert text is absent from rendered output
->assertSeeHtml('<strong>Alice</strong>')Assert raw HTML is present in output
->assertSet('name', 'Alice')Assert property equals expected value
->assertNotSet('name', 'Bob')Assert property does not equal value
->assertHasErrors(['name'])Assert validation errors exist for field
->assertHasErrors(['name' => 'required'])Assert specific validation rule failed
->assertHasNoErrors()Assert no validation errors exist
->assertHasNoErrors(['name'])Assert no errors for a specific field
->assertDispatched('post-created')Assert event was dispatched
->assertDispatched('post-created', id: 1)Assert event dispatched with data
->assertNotDispatched('post-created')Assert event was not dispatched
->assertRedirect('/dashboard')Assert redirect was triggered
->assertRedirectToRoute('dashboard')Assert redirect to named route
->assertStatus(200)Assert HTTP response status
->assertViewIs('livewire.my-component')Assert correct view is used
->assertViewHas('posts')Assert view data variable exists
->assertUnauthorized()Assert a 401 authorization error
->assertForbidden()Assert a 403 forbidden error
Livewire::actingAs($user)Authenticate a user for Livewire tests

Pagination

use Livewire\WithPagination;Add pagination trait to component
Post::paginate(10)Paginate Eloquent query in component
{{ $posts->links() }}Render pagination links in Blade template
{{ $posts->links('vendor.pagination.tailwind') }}Render links with custom view
$this->resetPage()Reset to page 1 (call on search/filter changes)
WithPagination + #[Url]WithPagination handles URL page binding automatically; do not redeclare $page manually
use Livewire\WithPagination; // supports cursorWithPagination also supports cursor pagination
Post::cursorPaginate(10)Use cursor-based pagination (faster on large tables)
$this->resetPage('cursor')Reset to page 1 (pass custom pageName if using non-default page name)
'pagination' => 'custom-pagination'Set default pagination view in config/livewire.php