skip to content

Livewire

Livewire builds reactive Laravel interfaces from server-rendered PHP components that sync state over AJAX requests. Interviewers weigh writing less JavaScript against a round trip per interaction.

on this pageshow

explore

questions

page 1 of 2

In Livewire, how do wire:click and wire:submit call component methods, and how are arguments passed to those methods?

level: juniorimportance: must knowfreq 65%

answer

  1. public method name in the directive
  2. arguments are JavaScript expressions
  3. wire:submit prevents default itself
  4. form inputs disabled while in flight
  5. type-hinted model resolved from its id

basics

~20 s

wire:click="addItem(42)" and wire:submit="checkout" send a request that calls that public method on the Livewire component. Arguments are JavaScript expressions sent as JSON; type-hinted models are resolved from ids and container services are injected. wire:submit prevents the browser submit itself.

solid answer

~40 s

`wire:click="addItem({{ $product->id }}, 2)"` tells Livewire to send a request that calls the **public** method `addItem()` on the component, with the arguments evaluated in the browser as JavaScript and sent as JSON. On the server, a type-hinted model parameter (`Product $product`) is resolved from the id, and container services such as a repository are injected before the passed values. `wire:submit="checkout"` on a `<form>` intercepts the submit event and calls `preventDefault()` itself, so no `.prevent` is needed, and it disables the form's inputs and submit button while the request runs. After the method returns, the component re-renders and the new HTML is morphed into the page. Because any public method can be called this way, arguments are untrusted input, just like request data.

code

html · 13 lines
html
<div>
    @foreach ($this->products as $product)
        <div wire:key="p-{{ $product->id }}">
            {{ $product->name }}
            <button wire:click="addItem({{ $product->id }}, 1)">Add</button>
        </div>
    @endforeach

    <form wire:submit="applyCoupon">
        <input type="text" wire:model="coupon">
        <button type="submit">Apply</button>
    </form>
</div>

go deeper

for a junior

Recall the directive syntax with arguments, that the method must be public, and that wire:submit prevents the default submit.

for a middle

Explain how arguments are evaluated in the browser, sent as JSON, and resolved to models or services on the server.

for a senior

Treat every public method and argument as an endpoint and input, keep helpers protected, and use type hints to constrain what arrives.

for a principal

Set conventions so component actions stay thin, delegate to services, and are reviewed like controller endpoints.

## Actions: public methods the browser can call An **action** in Livewire is a **public method** on the component class that the browser can invoke. Directives such as `wire:click` and `wire:submit` wire DOM events to actions: ```html <button wire:click="addItem({{ $product->id }}, 2)">Add two</button> <form wire:submit="checkout"> <input wire:model="coupon"> <button type="submit">Pay</button> </form> ``` When the event fires, Livewire sends a request carrying the component's snapshot plus a list of **calls** (method name and arguments). The server rebuilds the component, runs the method, re-renders the Blade view and returns the new HTML and state, which the browser morphs into the page. ## How arguments travel - The text inside the parentheses is a **JavaScript expression** evaluated in the browser. Blade's `{{ $product->id }}` is printed into it on the server first, so the browser sees `addItem(42, 2)`. - Strings need quotes: `wire:click="setSize('large')"`. - `$event` gives access to the DOM event, for example `wire:keydown.enter="search($event.target.value)"`. - Values are sent as JSON, so they arrive in PHP as strings, numbers, booleans, arrays or null, never as PHP objects. ## What PHP does with them The method's parameters are filled in order, with two conveniences: 1. **Model resolution**: a parameter type-hinted with an Eloquent model, `public function addItem(Product $product, int $qty)`, is looked up from the passed id, much like route model binding. 2. **Dependency injection**: parameters type-hinted with a class from the service container, `public function checkout(CartService $cart)`, are resolved by the container; the values from the browser fill the remaining parameters. ## wire:submit specifics | Behaviour | `wire:click` | `wire:submit` | |---|---|---| | Needs `.prevent` to stop default | Only for links and submit buttons | No, calls `preventDefault()` itself | | Disables form inputs while running | No | Yes, inputs and submit button inside the form | | Typical use | Buttons, toggles, row actions | Saving a whole form | `wire:submit` disables the form's controls during the request, which stops a double submit on a slow connection. ## Other listeners and modifiers `wire:` accepts any browser event name (`wire:keydown`, `wire:mouseenter`, `wire:change`), and modifiers such as `.prevent`, `.stop`, `.once`, `.debounce`, `.window`, `.outside` and key aliases like `.enter` or `.escape` come from Alpine's `x-on`, which Livewire uses underneath. ## What cannot be called - **Protected and private methods** cannot be called; the request fails with a method-not-found error. - `render()` is excluded even though it is public. - A method marked `#[Computed]` is read-only and throws if called as an action. Everything else that is public **can** be called from the browser's devtools, whether or not the template references it. That is why action parameters are treated as untrusted input and why helpers that must not be reachable are kept protected. ## Ending an action An action usually just changes state and lets the component re-render. It can also: - **Redirect**: `return redirect()->to('/cart');` or `$this->redirect('/cart')`; the browser navigates after the response. - **Return a value**: the value is sent back with the response and is available to JavaScript that called the action; a `wire:click` in Blade simply ignores it. - **Dispatch events** for other components, as in the example below. - **Throw**: a validation exception fills the error bag and the view shows errors; other exceptions surface like any Laravel error. ## A cart example On a product page, an add-to-cart button calls an action on the product card component: ```php public function addItem(Product $product, int $qty = 1): void { Cart::for(auth()->user())->add($product, $qty); $this->dispatch('cart-updated'); } ``` The action runs on the server, the card re-renders, and the dispatched event lets a separate cart counter in the header refresh itself.

  • In a Livewire action, what happens if the method is protected instead of public?
    It cannot be called from the browser. Livewire only dispatches calls to public methods defined on the component (excluding `render()`), so a call to a protected method fails with a method-not-found error. That is the standard way to keep internal helpers out of reach of devtools.
  • Why does a Livewire action receive "42" as a string when a method parameter is untyped?
    Arguments are sent as JSON from a JavaScript expression. `addItem({{ $id }})` prints a number, but values read from inputs or `$event.target.value` are strings. Add scalar type hints such as `int $qty` so PHP coerces them, and validate them as you would request input.

saying these in an interview costs you the question

  • wire:submit needs .prevent or the browser posts the form
  • Protected methods can be called from wire:click
  • Only methods referenced in the template can be called
  • Arguments arrive as PHP objects exactly as they were in Blade
  • wire:click reloads the page to run the method
open as a page

In a Livewire component's Alpine code, how do $wire reads, writes and method calls differ in when they reach the server?

level: juniorimportance: must knowfreq 50%

basics

~20 s

Reading $wire.guests and assigning $wire.guests = 3 stay in the browser; the assignment rides along with the next Livewire request. $wire.$set() sends a request by default, and calling $wire.checkAvailability() always does, resolving with the PHP return value.

open as a page

In Livewire, when does an input bound with wire:model send its value to the server, and what does the .live modifier change?

level: juniorimportance: must knowfreq 70%

basics

~20 s

By default wire:model is deferred: typing updates only client-side state, and the value reaches the server with the next action's request, such as a wire:submit. wire:model.live sends an update as the value changes, debounced 150 ms on text inputs.

open as a page

In Livewire, how do you pass data from a Blade view into a nested component, and when does that component's mount() method run?

level: juniorimportance: must knowfreq 60%

basics

~20 s

Pass props as attributes on <livewire:name /> (a colon prefix evaluates PHP) or in @livewire's array. mount() receives them by parameter name, or matching public properties are filled. mount() runs once, at creation, never on later requests.

open as a page

In a Livewire component, how do you run code whenever a user changes one public property, such as recomputing an order total?

level: juniorimportance: must knowfreq 58%

basics

~20 s

Define an updatedQuantity() method on the component: Livewire calls it after it writes a new quantity sent from the browser, so it can recompute the total. updatingQuantity() runs before the write; generic updating() and updated() receive the property name.

open as a page

In a Livewire component, how do wire:loading and wire:target show a spinner only while one specific action is running?

level: juniorimportance: must knowfreq 52%

basics

~20 s

wire:loading hides an element until the component sends a request and shows it until the response arrives; adding wire:target="refreshChart" limits it to requests that call that action, and .delay avoids a flash on fast responses.

open as a page

In a Livewire component, which methods can the browser call, and why must their arguments be treated as untrusted input?

level: juniorimportance: must knowfreq 55%

basics

~20 s

The browser can call any public, non-static method your Livewire component class declares, referenced in a template or not, except render(), lifecycle hooks and #[Computed] methods. Arguments arrive in an editable JSON request, so authorize and validate them.

open as a page

How do you test a Livewire newsletter sign-up component with Livewire::test(), set(), call() and assertSet()?

level: juniorimportance: must knowfreq 55%

basics

~10 s

Livewire::test('newsletter-signup') renders the component in the test, set('email', ...) updates a property and call('subscribe') runs an action, each as a simulated Livewire request; then assertSet, assertSee and database assertions check the result.

open as a page

In a Livewire component, how do you let a user attach a receipt file and then store it permanently when the expense claim is saved?

level: juniorimportance: must knowfreq 48%

basics

~10 s

Add the WithFileUploads trait, bind the file input with wire:model="receipt", and in the save action validate $this->receipt and call $this->receipt->store('receipts') or storeAs(), which returns the stored path.

open as a page

In Livewire, how does one component notify another with dispatch() and #[On], and how do to() and self() narrow who receives the event?

level: middleimportance: must knowfreq 60%

basics

~20 s

$this->dispatch('cart-updated', count: 3) queues a browser event returned with the response; any component with #[On('cart-updated')] on a public method runs it in a follow-up request, with count passed by name. ->to('cart-counter') targets one component; ->self() keeps it on the sender.

open as a page

How do you integrate a third-party date-picker widget into a Livewire booking form so re-renders don't break it and the date reaches PHP?

level: middleimportance: must knowfreq 45%

basics

~20 s

Wrap the picker's markup in wire:ignore so Livewire's DOM morph leaves it alone, load the library with @assets, initialise it in the component's script, and push each selected date into $wire.checkIn; watch that property to reflect server changes.

open as a page

In a Livewire component, how do #[Validate] attributes and $this->validate() work together, and how does real-time validation happen?

level: middleimportance: must knowfreq 55%

basics

~20 s

#[Validate('required|numeric')] on a Livewire public property registers its rules and validates that property whenever an update for it reaches the server, so .live or .live.blur bindings give real-time errors. $this->validate() checks every rule before saving and throws on failure.

open as a page

In a Livewire component, what does the #[Computed] attribute do, and when does the method behind it run again?

level: middleimportance: must knowfreq 55%

basics

~20 s

#[Computed] turns a Livewire method into a property memoized for one request: the first $this->name read runs it, later reads reuse the result. Each new request runs it again on first read; unset() busts it, persist: true caches across requests.

open as a page

In a Livewire component, which lifecycle hooks run only on the first render, which only on later requests, and which on every request?

level: middleimportance: must knowfreq 52%

basics

~10 s

mount() runs only on the first render; hydrate() and hydrateFoo() run only on later requests; boot(), booted(), dehydrate() and dehydrateFoo() run on every request, and rendering()/rendered() whenever the view renders.

open as a page

In Livewire 4, how do #[Lazy] and #[Defer] keep a slow sales-chart component from blocking the page, and how do they differ?

level: middleimportance: must knowfreq 42%

basics

~20 s

Both render a placeholder instead of the component on the first page load and fetch the real component in a separate request; #[Lazy] loads it when it scrolls into view, #[Defer] loads it immediately after the page loads.

open as a page

In a Livewire component test, how do assertHasErrors() and assertDispatched() check validation failures and events, and what do their arguments match?

level: middleimportance: must knowfreq 45%

basics

~10 s

assertHasErrors('email') checks the field has an error, and assertHasErrors(['email' => 'email']) that a specific rule or message failed. assertDispatched('subscribed') checks an event name, and named arguments check only the parameters you list.

open as a page

In Livewire, where does an uploaded file live before your action stores it, and what do the temporary_file_upload config defaults control?

level: middleimportance: must knowfreq 34%

basics

~20 s

Livewire keeps uploads in a livewire-tmp directory on the default filesystem disk until you store them; config/livewire.php's temporary_file_upload block sets that disk and directory, global rules (12 MB), the upload route's middleware, the signed-URL lifetime and cleanup.

open as a page

On a Livewire payroll screen, a public $userId set in mount() is edited in the browser before Save - why doesn't the snapshot checksum stop it, and what does?

level: seniorimportance: must knowfreq 50%

basics

~20 s

The checksum signs only the snapshot the server issued; property updates travel beside it by design, since that is how wire:model works. #[Locked], a model-typed property, or an authorization check in the save action stops the edit.

open as a page

In Livewire, what do the magic actions $refresh, $set, $toggle and $parent do when used in a wire:click directive?

level: juniorimportance: should knowfreq 40%

basics

~20 s

Livewire's magic actions run without a method of your own: $refresh re-renders the component, $set('prop', value) assigns a public property, $toggle('prop') flips a boolean, and $parent.remove(3) calls an action or reads a property on the parent component.

open as a page

In Livewire 4, what does php artisan make:livewire create by default, and how do the sfc, mfc and class component formats differ?

level: juniorimportance: should knowfreq 50%

basics

~20 s

In Livewire 4, make:livewire creates a single-file component by default: one ⚡-prefixed .blade.php file holding an anonymous component class above its Blade markup. --mfc splits it into a directory of files; --class makes the v3-style class plus separate view.

open as a page

In a Livewire component, how do you show an upload progress bar and a cancel button while a receipt file is uploading?

level: juniorimportance: should knowfreq 32%

basics

~10 s

Livewire dispatches livewire-upload-start, -progress, -finish, -error and -cancel browser events from the file input; an Alpine wrapper can read $event.detail.progress into a progress bar, and wire:click="$cancelUpload('receipt')" aborts the upload.

open as a page

In Livewire, how do the #[Reactive] and #[Modelable] attributes differ when a parent and a nested child component share a value?

level: middleimportance: should knowfreq 38%

basics

~20 s

#[Reactive] makes a Livewire child property follow the value the parent passes on each parent update, one way; the child may not change it. #[Modelable] lets the parent put wire:model on the child tag, syncing both ways.

open as a page

Why do Livewire 4's docs discourage $wire.$entangle() for sharing state with Alpine, and what should you use instead?

level: middleimportance: should knowfreq 25%

basics

~20 s

$wire.$entangle() creates a second Alpine copy of a Livewire property and keeps the two in sync, which duplicates state and causes ordering and performance problems. Livewire 4 keeps it only for compatibility; read and write $wire.prop directly instead.

open as a page

In a Livewire view, why pass PHP data into an Alpine x-data expression with @js rather than echoing json_encode() output?

level: middleimportance: should knowfreq 30%

basics

~20 s

@js($slots) compiles to Laravel's Js::from(), which JSON-encodes with quotes, apostrophes, angle brackets and ampersands hex-escaped, so the value is a valid JavaScript expression inside an HTML attribute or script tag and cannot break out of it.

open as a page

In Livewire 4, how do the wire:model modifiers .blur, .change, .enter and .deep behave, and why does .live.blur differ from .blur.live?

level: middleimportance: should knowfreq 42%

basics

~20 s

In Livewire 4, modifiers before .live set when client-side state syncs; modifiers after .live set when the request is sent. .blur.live syncs and sends on blur; .live.blur syncs per keystroke, sends on blur. .deep hears child events again.

open as a page

In Livewire, what is a Form object created with php artisan livewire:form, and how do you bind, validate and reset its fields?

level: middleimportance: should knowfreq 40%

basics

~20 s

A Livewire Form object is a class extending Livewire\Form (livewire:form writes it to app/Livewire/Forms) that holds a form's fields, #[Validate] rules and save logic. A component declares public FilterForm $form; inputs bind to form.field, and $this->form->validate() and reset() act on the form.

open as a page

In Livewire 4, how do you serve a component as a full page with Route::livewire, and how does #[Layout] choose the page's layout?

level: middleimportance: should knowfreq 40%

basics

~20 s

Route::livewire('/stock', 'pages::stock.dashboard') registers a GET route that renders the component inside a layout. The layout is config livewire.component_layout (layouts::app) unless #[Layout('...')] on the class or ->layout() in render() overrides it; route parameters reach mount() by name.

open as a page

In a Livewire component, which types can a public property hold, and why can't a protected property keep state between requests?

level: middleimportance: should knowfreq 45%

basics

~20 s

Livewire public properties must survive a JSON round trip: primitives and arrays, BackedEnum, Collection, Eloquent models and collections, DateTime/Carbon and Stringable, or a Wireable class. Protected properties are never sent, so each request starts them from their declared default.

open as a page

In Livewire 4, when a user edits the quantity of one row in a public $items array, which update hooks fire and with what arguments?

level: middleimportance: should knowfreq 32%

basics

~10 s

For an update to items.2.quantity, Livewire 4 calls updating('items.2.quantity', $value) and updatingItems($value, '2.quantity') before the write, then updated('items.2.quantity', $value) and updatedItems($value, '2.quantity') after all updates are written.

open as a page

In a Livewire component, what does the exception($e, $stopPropagation) hook do, and when would you use it instead of a try/catch?

level: middleimportance: should knowfreq 24%

basics

~10 s

exception($e, $stopPropagation) runs when an action or lifecycle hook on the component throws; calling $stopPropagation() swallows the exception, otherwise it is rethrown to Laravel's normal handling.

open as a page

showing 1–30 of 49