Professional Documents
Culture Documents
Livewire
Livewire
INSTALL LIVEWIRE
Include the PHP.
Include the JavaScript (on every page that will be using Livewire).
CREATE A COMPONENT
Run the following command to generate a new Livewire component called counter.
TEMPLATE DIRECTIVES
These are directives added to elements within Livewire component templates.
Directive Description
wire:key="foo" Acts as a reference point for Livewire's DOM diffing
system. Useful for adding/removing elements, and
keeping track of lists.
wire:click="foo" Listens for a "click" event, and fires the "foo" method
in the component.
wire:click.prefetch="foo" Listens for a "mouseenter" event, and "prefetches"
the result of the "foo" method in the component.
Then, if it is clicked, will swap in the "prefetched"
result (without an extra request), if it's not clicked,
will throw away the cached result.
wire:keydown.enter="foo" Listens for a keydown event on the enter key, which
fires the "foo" method in the component.
wire:foo="bar" Listens for a browser event called "foo". (You can
listen for any browser DOM event - not just those
fired by Livewire).
wire:model="foo" Assuming $foo is a public property on the
component class, every time an input element with
this directive is updated, the property synchronizes
with its value.
wire:model.debounce.100ms="foo" Debounces the input events emitted by the element
every 100 milliseconds.
wire:model.lazy="foo" Lazily syncs the input with its corresponding
component property at rest.
wire:model.defer="foo" Defers syncing the input with the Livewire property
until an "action" is performed. This saves drastically
on server roundtrips.
wire:poll.500ms="foo" Runs the "foo" method on the component class every
500 milliseconds.
wire:init="foo" Runs the "foo" method on the component
immediately after it renders on the page.
wire:loading Hides the element by default, and makes it visible
while network requests are in transit.
wire:loading.class="foo" Adds the foo class to the element while network
requests are in transit.
wire:loading.class.remove="foo" Removes the foo class while network requests are in
transit.
wire:loading.attr="disabled" Adds the disabled="true" attribute while network
requests are in transit.
wire:dirty Hides the element by default, and makes it visible
while the element's state is "dirty" (different from
what exists on the backend).
wire:dirty.class="foo" Adds the foo class to the element while it's dirty.
wire:dirty.class.remove="foo" Removes the foo class while the element is dirty.
wire:dirty.attr="disabled" Adds the disabled="true" attribute while the
element's dirty.
wire:target="foo" Scopes wire:loading and wire:dirty functionality
to a specific action.
wire:ignore Instructs Livewire to not update the element or its
children when updating the DOM from a server
request. Useful when using third-party JavaScript
libraries within Livewire components.
wire:ignore.self The "self" modifier restricts updates to the element
itself, but allows modifications to its children.
API Description
$wire.foo Get the value of the "foo" property on the
Livewire component
$wire.foo = 'bar' Set the value of the "foo" property on the
Livewire component
$wire.bar(..args) Call the "bar" method (with params) on the
Livewire component
let baz = await $wire.bar(..args) Call the "bar" method, but wait for the response
and set baz to it
$wire.on('foo', (..args) => {}) Call a function when the "foo" event is emitted
$wire.emit('foo', ...args) Emit the "foo" event to all Livewire components
$wire.emitUp('foo', ...args) Emit the "foo" event to parent components
$wire.emitSelf('foo', ...args) Emit the "foo" event only to this component
$wire.get('foo') Get the "foo" property
$wire.set('foo', 'bar') Set the "foo" property on the component
$wire.set('foo', 'bar', true) Defer setting the "foo" property on the
component
$wire.call('foo', ..args) Call the "foo" method with params on the
component
x-data="{ foo: Entagle the value of "foo" between Livewire and
$wire.entangle('foo') }"
Alpine
$wire.entangle('foo').defer Only update Livewire's "foo" next time a
Livewire request is fired
JAVASCRIPT HOOKS
These are "hooks" you can listen for in JavaScript. These allow you to hook into very specific parts
of a Livewire component's JavaScript lifecycle for third-party packages or deep customizations.
The abilities unlocked here are immense. A significant portion of Livewire's core uses these hooks
to provide functionality.
Name Description
boot() Called on all requests, immediately after the component is
instantiated, but before any other lifecycle methods are called
booted() Called on all requests, after the component is mounted or
hydrated, but before any update methods are called
mount(...$params) Called when a Livewire component is newed up (think of it
like a constructor)
hydrate() Called on subsequent Livewire requests after the component
has been hydrated, but before any other action occurs
hydrateFoo() Runs after a property called $foo is hydrated
dehydrate() Called after render(), but before the component has been
dehydrated and sent to the frontend
dehydrateFoo() Runs before a property called $foo is dehydrated
updating() Runs before any update to the Livewire component's data
(Using wire:model, not directly inside PHP)
updated($field, Called after a property has been updated
$newValue)
updatingFoo() Runs before a property called $foo is updated
updatedFoo($newValue) Called after the "foo" property has been updated
updatingFooBar() Runs before updating a nested property bar on the $foo
property
updatedFooBar($newValue) Called after the nested "bar" key on the "foo" property has
been updated
render() Called before "dehydrate" and renders the Blade view for the
component
Name Description
WithPagination This trait enables Livewire-based pagination instead of Laravel's stock
pagination system. Read Docs
WithFileUploads This trait enables adding wire:model to an input of type="file". Read
Docs
CLASS METHODS
Name Description
$this->emit($eventName, ...$params) Emit an event to other components on the
page
$this->emit($eventName, ...$params)- Emit an event to parent components on
>up()
the page
$this->emit($eventName, ...$params)- Emit an event only to THIS component
>self()
$this->emit($eventName, ...$params)- Emit an event to any component
>to($componentName)
matching the provided name
$this->dispatchBrowserEvent($eventName, Dispatch a browser event from this
...$params)
component's root element
$this->validate() Run the validation rules provided in the
$rules property against the public
component properties
$this->validate($rules, $messages) Run the provided validation rules against
the public properties
$this->validateOnly($propertyName) Run the $rules property validation
against a specific property provided and
not others
$this->validateOnly($propertyName, Run the provided validation rules against
$rules, $messages)
a specific property name
$this->redirect($url) Redirect to a new URL when the
Livewire request finishes and reaches the
frontend
$this->redirectRoute($routeName) Redirect to a specific route name
$this->skipRender() Skip running the ->render() method for
the current request. (Usually for
performance reasons)
$this->addError($name, $error) Add a specific error name and value to
the component's error bag manually
$this->resetValidation() Reset the currently stored validation
errors (clear them)
$this->fill([...$propertyData]) Set public property names to provided
values in bulk
$this->reset() Reset all public properties to their initial
(pre-mount) state
$this->reset($field) Reset a specific public property to its pre-
mount state
$this->reset([...$fields]) Reset multiple specific properties
$this->all() Return key->value pairs of property data
$this->only([...$propertyNames]) Return key->value pairs of property data
only for a specific set of property names
$this->except([...$propertyNames]) Return key->value pairs of property data
except for a specific set of property
names
ARTISAN COMMANDS
These are the artisan commands Livewire makes available to make frequent tasks like creating
a component easier.
Name Params Description
artisan make:livewire Create a new component
artisan livewire:make Create a new component
artisan livewire:copy Copy a component
artisan livewire:move Move a component
artisan livewire:delete Delete a component
artisan livewire:touch Alias for livewire:make
artisan livewire:cp Alias for livewire:copy
artisan livewire:mv Alias for livewire:move
artisan livewire:rm Alias for livewire:delete
artisan livewire:stubs Publish Livewire stubs (used in the above
commands) for local modification
artisan livewire:publish Publish Livewire's config file to your
project (config/livewire.php)
artisan livewire:publish - Publish Livewire's config file AND its
-assets
frontend assets to your project
artisan Configure your cloud disk driver's S3
livewire:configure-s3-
bucket to clear temporary uploads after 24
upload-cleanup
hours
PHP LIFECYCLE HOOKS
These are hooks provided by Livewire in PHP for listening to lifecycle occurences at a global level
(not at a component level). These are used internally to provide a significant portion of Livewire's
core functionality, and can be used in ServiceProviders to further extend Livewire yourself.
INSTALLATION
Requirements
1. PHP 7.2.5 or higher
2. Laravel 7.0 or higher
Visit the composer.json file on Github for the complete list of package requirements.
To keep the assets up-to-date and avoid issues in future updates, we highly recommend adding
the command to the post-autoload-dump scripts in your composer.json file:
Configuring The Asset Base URL
By default, Livewire serves its JavaScript portion (livewire.js) from the following route in your
app: /livewire/livewire.js.
There are two scenarios that will cause this default behavior to break:
1. You publish the Livewire assets and are now serving them from a sub-folder like "assets".
2. Your app is hosted on a non-root path on your domain. For example: https://your-
laravel-app.com/application. In this case, the actual assets will be served from
/application/livewire/livewire.js, but the generated script tag, will be trying to fetch
/livewire/livewire.js.
To solve either of these issues, you can configure the "asset_url" in config/livewire.php to
customize what's prepended to the src="" attribute.
For example, after publishing Livewire's config file, here are the settings that would fix the above
two issues:
1. 'asset_url' => '/assets'
2. 'asset_url' => '/application'
MAKING COMPONENTS
Introduction
Run the following artisan command to create a new Livewire component:
• resources/views/livewire/show-posts.blade.php
If you wish to create components within sub-folders, you can use the following different syntaxes:
• resources/views/livewire/post/show.blade.php
Generating Tests
Optionally, you can include the --test flag when creating a component, and a test file will be
created for you as well.
Inline Components
If you wish to create Inline components (Components without .blade.php files), you can add the
--inline flag to the command:
Inline Components
The most basic way to render a Livewire component on a page is using the <livewire: tag syntax:
If you have a component inside of a sub-folder with its own namespace, you must use a dot (.)
prefixed with the namespace.
Parameters
Passing Parameters
You can pass data into a component by passing additional parameters into the <livewire: tag.
For example, let's say we have a show-post component. Here's how you would pass in a $post
model.
Alternatively, this is how you can pass in parameters using the Blade directive.
Receiving Parameters
Livewire will automatically assign parameters to matching public properties.
If for whatever reason, this automatic behavior doesn't work well for you, you can intercept
parameters using the mount() method:
In Livewire components, you use mount() instead of a class constructor
__construct() like you may be used to. NB: mount() is only ever called when the
component is first mounted and will not be called again even when the component is
refreshed or rerendered.
Like a controller, you can inject dependencies by adding type-hinted parameters before passed-in
ones.
Full-Page Components
If the main content of a page is a Livewire component, you can pass the component directly into a
Laravel route as if it were a controller.
By default, Livewire will render the ShowPosts component into the {{ $slot }} of a blade layout
component located at: resources/views/layouts/app.blade.php.
If you need even more control, you can use the ->layout() method on the view instance you
return from render().
If your layout has an associated class file, you will need to reference that for any custom logic or
properties.
If you are using a non-default slot in the component, you can also chain on ->slot():
Alternatively, Livewire supports using traditional Blade layout files with @extends.
If you need to configure the @section for the component to use, you can configure that as well
with the ->section() method:
If you need to pass data from your components to your layout, you can pass the data along with
the layout method:
In some cases you don't need to pass your layout name or you want to pass layout data separately,
you can use layoutData method:
Route Parameters
Often you need to access route parameters inside your controller methods. Because we are no
longer using controllers, Livewire attempts to mimic this behavior through its mount method. For
example:
As you can see, the mount method in a Livewire component is acting like a controller method
would as far as its parameters go. If you visit /post/123, the $id variable passed into the mount
method will contain the value 123.
Route Model Binding
Like you would expect, Livewire components implement all functionality you're used to in your
controllers including route model binding. For example:
If you are using PHP 7.4, you can also typehint class properties, and Livewire will automatically
route-model bind to them. The following component's $post property will be automatically
injected with no need for the mount() method.
In simple components, you don't need to define a `render` method yourself. The base
Livewire component class has a dynamic `render` method included.
Returning Blade Views
The render() method is expected to return a Blade view, therefore, you can compare it to writing
a controller method. Here is an example:
Make sure your Blade view only has ONE root element.
Introduction
Livewire components store and track data as public properties on the component class.
Public properties in Livewire are automatically made available to the view. No need to explicitly
pass them into the view (although you can if you want).
Important Notes
Here are three ESSENTIAL things to note about public properties before embarking on your
Livewire journey:
1. Property names can't conflict with property names reserved for Livewire (e.g. rules or
messages)
2. Data stored in public properties is made visible to the front-end JavaScript. Therefore, you
SHOULD NOT store sensitive data in them.
3. Properties can ONLY be either JavaScript-friendly data types (string, int, array,
boolean), OR one of the following PHP types: Stringable, Collection, DateTime,
Model, EloquentCollection.
Initializing Properties
You can initialize properties using the mount method of your component.
Livewire also makes a $this->fill() method available to you for cases where you have to set
lots of properties and want to remove visual noise.
Additionally, Livewire offers $this->reset() and $this->resetExcept() to programmatically
reset public property values to their initial state. This is useful for cleaning input fields after
performing an action.
Data Binding
If you've used front-end frameworks like Vue, or Angular, you are already familiar with this
concept. However, if you are new to this concept, Livewire can "bind" (or "synchronize") the
current value of some HTML element with a specific property in your component.
When the user types something into the text field, the value of the $message property will
automatically update.
Internally, Livewire will listen for an input event on the element, and when triggered, it will send
an AJAX request to re-render the component with the new data.
You can add wire:model to any element that dispatches an input event. Even custom
elements, or third-party JavaScript libraries.
<input type="radio">
<input type="checkbox">
<select>
<textarea>
Binding Nested Data
Livewire supports binding to nested data inside arrays using dot notation:
Debouncing Input
By default, Livewire applies a 150ms debounce to text inputs. This avoids too many network
requests being sent as a user types into a text field.
If you wish to override this default (or add it to a non-text input), Livewire offers a "debounce"
modifier. If you want to apply a half-second debounce to an input, you would include the modifier
like so:
Lazy Updating
By default, Livewire sends a request to the server after every input event (or change in some
cases). This is usually fine for things like <select> elements that don't typically fire rapid updates,
however, this is often unnecessary for text fields that update as the user types.
In those cases, use the lazy directive modifier to listen for the native change event.
Now, the $message property will only be updated when the user clicks away from the input field.
Deferred Updating
In cases where you don't need data updates to happen live, Livewire has a .defer modifier that
batches data updates with the next network request.
When the user presses "Search", Livewire will send ONE network request that contains both the
new "query" state, AND the "search" action to perform.
This can drastically cut down on network usage when it's not needed.
For example, let’s say we have a custom object in our app called Settings. Rather than just store
settings data as a plain array on our Livewire component, we can attach associated behavior to this
data with a convenient wrapper object or DTO like Settings:
Now you can freely use this object as a public property of your component as long as that object
implements the Livewire\Wireable interface AND the property is typhinted like so:
And as you can see, changes to the component are persisted between requests because, with
Wireable, Livewire knows how to “dehydrate” and “re-hydrate” this property on your component.
If words like “hydrate” or “dehydrate” in the context of Livewire are fuzzy for you, give this
post a quick read.
Computed Properties
Livewire offers an API for accessing dynamic properties. This is especially helpful for deriving
properties from the database or another persistent store like a cache.
Now, you can access $this->post from either the component's class or Blade view:
Computed properties are cached for an individual Livewire request lifecycle. Meaning,
if you call `$this->post` 5 times in a component's blade view, it won't make a separate
database query every time.
ACTIONS
Introduction
The goal of actions in Livewire is to be able to easily listen to page interactions, and call a method
on your Livewire component (re-rendering the component).
Livewire currently offers a handful of directives to make listening to browser events trivial. The
common format for all of them is: wire:[dispatched browser event]="[action]".
Here are some common events you may need to listen for:
Event Directive
click wire:click
keydown wire:keydown
submit wire:submit
Here are a few examples of each in HTML:
You can listen for any event dispatched by the element you are binding to. Let's say
you have an element that dispatches a browser event called "foo", you could listen for
that event like so: <button wire:foo="someAction">
Like the above example using `wire:submit.prevent` directly at the form opening tag
will generate "readonly" properties for all html elements inside the form during the
requests.
Extra parameters passed to an action, will be passed through to the component's method as standard
PHP params:
Action parameters are also capable of directly resolving a model by its key using a type hint.
If your action requires any services that should be resolved via Laravel's dependency injection
container, you can list them in the action's signature before any additional parameters:
Event Modifiers
Like you saw in the keydown example, Livewire directives sometimes offer "modifiers" to add
extra functionality to an event. Below are the available modifiers that can be used with any event.
Modifier Description
stop Equivalent of event.stopPropagation()
self Only triggers an action if the event was triggered on itself. This prevents
outer elements from catching events that were triggered from a child
element. (Like often in the case of registering a listener on a modal
backdrop)
debounce.150ms Adds an Xms debounce to the handling of the action.
Keydown Modifiers
To listen for specific keys on keydown events, you can pass the name of the key as a modifier.
You can directly use any valid key names exposed via KeyboardEvent.key as modifiers by
converting them to kebab-case.
In the above example, the handler will only be called if event.key is equal to 'PageDown'.
Magic Actions
In Livewire, there are some "magic" actions that are usually prefixed with a "$" symbol:
Function Description
$emit('event', Will emit an event on the global event bus, with the provided params
...params)
$event A special variable that holds the value of the event fired that triggered
the action. Example usage:
wire:change="setSomeProperty($event.target.value)"
You can pass these as the value of an event listener to do special things in Livewire.
Let's take $set() for example. It can be used to manually set a component property's value.
Consider the Counter component's view.
Before
After
Notice that we are no longer calling the setMessageToHello function, we are directly specifying,
what we want data set to.
It can also be used in the backend when listening for an event. For example, if you have one
component that emits an event like this:
Then in another component you can use a magic action for example $refresh() instead of having
to point the listener to a method:
EVENTS
Introduction
Livewire components can communicate with each other through a global event system. As long as
two Livewire components are living on the same page, they can communicate using events and
listeners.
Firing Events
There are multiple ways to fire events from Livewire components.
Event Listeners
Event listeners are registered in the $listeners property of your Livewire components.
Listeners are a key->value pair where the key is the event to listen for, and the value is the method
to call on the component.
Now when any other component on the page emits a postAdded event, this component will pick
it up and fire the incrementPostCount method on itself.
If the name of the event and the method you're calling match, you can leave out the
key. For example: protected $listeners = ['postAdded']; will call the
postAdded method when the postAdded event is emitted.
If you need to name event listeners dynamically, you can substitute the $listeners property for
the getListeners() protected method on the component:
getListeners() will only dynamically generate the names of listeners when the
component is mounted. Once the listeners are setup, these can't be changed.
Passing Parameters
You can also send parameters with an event emission.
Scoping Events
(Now, if the button is clicked, the "postAdded" event will only be emitted to counter components)
Scoping To Self
Sometimes you may only want to emit an event on the component that fired the event.
(Now, if the button is clicked, the "postAdded" event will only be emitted to the instance of the
component that it was emitted from.)
You are able to listen for this window event with JavaScript:
AlpineJS allows you to easily listen for these window events within your HTML:
LIFECYCLE HOOKS
Class Hooks
Each Livewire component undergoes a lifecycle. Lifecycle hooks allow you to run code at any
part of the component's lifecyle, or before specific properties are updated.
Hooks Description
boot Runs on every request, immediately after the component is instantiated, but
before any other lifecycle methods are called
booted Runs on every request, after the component is mounted or hydrated, but
before any update methods are called
mount Runs once, immediately after the component is instantiated, but before
render() is called. This is only called once on initial page load and never
called again, even on component refreshes
hydrate Runs on every subsequent request, after the component is hydrated, but
before an action is performed, or render() is called
hydrateFoo Runs after a property called $foo is hydrated
dehydrate Runs on every subsequent request, before the component is dehydrated, but
after render() is called
dehydrateFoo Runs before a property called $foo is dehydrated
updating Runs before any update to the Livewire component's data (Using
wire:model, not directly inside PHP)
updated Runs after any update to the Livewire component's data (Using
wire:model, not directly inside PHP)
updatingFoo Runs before a property called $foo is updated. Array properties have an
additional $key argument passed to this function to specify changing
element inside array, like updatingArray($value, $key)
updatedFoo Runs after a property called $foo is updated. Array properties have
additional $key argument as above
updatingFooBar Runs before updating a nested property bar on the $foo property or a
multiword property such as $fooBar or $foo_bar
updatedFooBar Runs after updating a nested property bar on the $foo property or a
multiword property such as $fooBar or $foo_bar
Please note that mutating a property directly inside a Livewire component class doesn't
trigger any of the updating/updated hooks.
Javascript Hooks
Livewire gives you the opportunity to execute javascript during certain events.
Hooks Description
component.initialized Called when a component has been initialized on the page by
Livewire
element.initialized Called when Livewire initializes an individual element
element.updating Called before Livewire updates an element during its DOM-diffing
cycle after a network roundtrip
element.updated Called after Livewire updates an element during its DOM-diffing
cycle after a network roundtrip
element.removed Called after Livewire removes an element during its DOM-diffing
cycle
message.sent Called when a Livewire update triggers a message sent to the server
via AJAX
message.failed Called if the message send fails for some reason
message.received Called when a message has finished its roudtrip, but before Livewire
updates the DOM
message.processed Called after Livewire processes all side effects (including DOM-
diffing) from a message
NESTING COMPONENTS
Introduction
Livewire supports nesting components. Component nesting can be an extremely powerful
technique, but there are a few gotchas worth mentioning up-front:
1. Nested components CAN accept data parameters from their parents, HOWEVER they are
not reactive like props from a Vue component.
2. Livewire components should NOT be used for extracting Blade snippets into separate files.
For these cases, Blade includes or components are preferable.
If you are on Laravel 7 or above, you can use the tag syntax.
Each component will need its own unique wire:key, but using the method above will lead to both
sibling components having the same key, which will cause unforeseen issues. To combat this, you
could ensure that each wire:key is unique by prefixing it with the component name, for example:
COMPONENT FEATURES
VALIDATION
Introduction
Validation in Livewire should feel similar to standard form validation in Laravel. In short,
Livewire provides a $rules property for setting validation rules on a per-component basis, and a
$this->validate() method for validating a component's properties using those rules.
You can also add custom key/message pairs to the error bag.
If you need to define rules dynamically, you can substitute the $rules property for the rules()
method on the component:
Real-time Validation
Sometimes it's useful to validate a form field as a user types into it. Livewire makes "real-time"
validation simple with the $this->validateOnly() method.
To validate an input field after every update, we can use Livewire's updated hook:
Let's break down exactly what is happening in this example:
The user types into the "name" field
As the user types in their name, a validation message is shown if it's less than 6 characters
The user can switch to entering their email, and the validation message for the name still shows
When the user submits the form, there is a final validation check, and the data is persisted.
If you are wondering, "why do I need validateOnly? Can't I just use validate?". The reason is
because otherwise, every single update to any field would validate ALL of the fields. This can be
a jarring user experience. Imagine if you typed one character into the first field of a form, and all
of a sudden every single field had a validation message. validateOnly prevents that, and only
validates the current field being updated.
If you want to keep the default Laravel validation messages, but just customize the :attribute
portion of the message, you can specify custom attribute names using the
$validationAttributes property.
You can substitute the $messages property for the messages() method on the component.
If you are not using the global $rules validation property, then you can pass custom messages
and attributes directly into validate().
Direct Error Message Manipulation
The validate() and validateOnly() methods should handle most cases, but sometimes you
may want direct control over Livewire's internal ErrorBag.
Livewire provides a handful of methods for you to directly manipulate the ErrorBag.
From anywhere inside a Livewire component class, you can call the following methods:
Access Validator instance
Sometimes you may want to access the Validator instance that Livewire uses in the validate()
and validateOnly() methods. This is possible using the withValidator method. The closure
you provide receives the fully constructed validator as an argument, allowing you to call any of its
methods before the validation rules are actually evaluated.
Testing Validation
Livewire provides useful testing utilities for validation scenarios. Let's write a simple test for the
original "Contact Form" component.
This is useful, but we can take it one step further and actually test against specific validation rules:
Livewire also offers the inverse of assertHasErrors -> assertHasNoErrors():
For more examples of supported syntax for these two methods, take a look at the Testing Docs.
Custom validators
If you wish to use your own validation system in Livewire, that isn't a problem. Livewire will catch
ValidationException and provide the errors to the view just like using $this->validate().
For example:
You might be wondering if you can use Laravel's "FormRequest"s. Due to the nature
of Livewire, hooking into the http request wouldn't make sense. For now, this
functionality is not possible or recommended.
FILE UPLOADS
Basic Upload
Note: Your Livewire version must be >= 1.2.0 to use this feature.
First, add the WithFileUploads trait to your component. Now you can use wire:model on file
inputs as if they were any other input type and Livewire will take care of the rest.
However, there is more happening under the hood to make file uploads work in Livewire. Here's
a glimpse at what goes on when a user selects a file to upload:
1. When a new file is selected, Livewire's JavaScript makes an initial request to the
component on the server to get a temporary "signed" upload URL.
2. Once the URL is received, JavaScript then does the actual "upload" to the signed URL,
storing the upload in a temporary directory designated by Livewire and returning the new
temporary file's unique hash ID.
3. Once the file is uploaded and the unique hash ID is generated, Livewire's JavaScript makes
a final request to the component on the server telling it to "set" the desired public property
to the new temporary file.
4. Now the public property (in this case $photo) is set to the temporary file upload and is
ready to be stored or validated at any point.
However, you may want to customize the file name of the stored file, or even specify a specific
storage "disk" to store the file on (maybe in an S3 bucket for example).
Livewire honors the same API's Laravel uses for storing uploaded files, so feel free to browse
Laravel's documentation. However, here are a few common storage scenarios for you:
The methods above should provide enough flexibility for storing the uploaded files exactly how
you want to.
For more information on Laravel's File Validation utilities, visit the documentation.
Real-time Validation
It's possible to validate a user's upload in real-time, BEFORE they press "submit".
Again, you can accomplish this like you would any other input type in Livewire:
Now, when user selects a file (After Livewire uploads the file to a temporary directory) the file
will be validated and the user will receive an error BEFORE they submit the form.
Livewire makes this trivial with the ->temporaryUrl() method on uploaded files.
Note: for security reasons, temporary urls are only supported for image uploads.
Livewire takes care of this complexity, by providing a temporary, signed URL that pretends to be
the uploaded image so that your page can show something to your users.
This URL is protected against showing files in directories above the temporary directory of course
and because it's signed temporarily, users can't abuse this URL to preview other files on your
system.
don't hit your Laravel app server for this preview at all.
For more specifics on testing file uploads, reference Laravel's file upload testing documentation.
By default, Livewire uses the default filesystem disk configuration (usually local), and stores the
files under a folder called livewire-tmp/.
This means that file uploads are always hitting your server; even if you choose to store them in an
S3 bucket later.
If you wish to bypass this system and instead store Livewire's temporary uploads in an S3 bucket,
you can configure that behavior easily:
In your config/livewire.php file, set livewire.temporary_file_upload.disk to s3 (or
another custom disk that uses the s3 driver):
Now, when a user uploads a file, the file will never actually hit your server. It will be uploaded
directly to your S3 bucket, under the sub-directory: livewire-tmp/.
To configure this behavior, simply run the following artisan command from the environment that
has the S3 bucket configured.
Now, any temporary files older than 24 hours will be cleaned up by S3 automatically.
If you are not using S3, Livewire will handle the file cleanup automatically. No need to
run this command.
Loading Indicators
Although wire:model for file uploads works differently than other wire:model input types under
the hood, the interface for showing loading indicators remains the same.
You can display a loading indicator scoped to the file upload like so:
Now, while the file is uploading the "Uploading..." message will be shown and then hidden when
the upload is finished.
The functions exist on the JavaScript component object, which can be accessed using the
convenience Blade directive: @this. If you haven't seen @this before, you can read more about it
here.
Configuration
Because Livewire stores all file uploads temporarily before the developer has a chance to validate
or store them, Livewire assumes some default handling of all file uploads.
Global Validation
By default, Livewire will validate ALL temporary file uploads with the following rules:
file|max:12288 (Must be a file less than 12MB).
If you wish to customize this, you can configure exactly what validate rules should run on all
temporary file uploads inside config/livewire.php:
Global Middleware
The temporary file upload endpoint has throttling middleware by default. You can customize
exactly what middleware this endpoint uses with the following configuration variable:
Introduction
Livewire supports triggering file downloads for users with a simple, intuitive API.
To trigger a file download, you can return a Laravel file download from any component action.
Livewire should handle any file download that Laravel would. Here are a few other utilities you
might use:
Testing File Downloads
Testing file downloads is simple with livewire.
Here is an example of testing the component above and making sure the export was downloaded.
QUERY STRING
Introduction
Sometimes it's useful to update the browser's query string when your component state changes.
For example, if you were building a "search posts" component, and wanted the query string to
reflect the current search value like so:
https://your-app.com/search-posts?search=some-search-string
This way, when a user hits the back button, or bookmarks the page, you can get the initial state out
of the query string, rather than resetting the component every time.
In these cases, you can add a property's name to protected $queryString, and Livewire will
update the query string every time the property value changes, and also update the property when
the query string changes.
Keeping A Clean Query String
In the case above, when the search property is empty, the query string will look like this:
?search=
There are other cases where you might want to only represent a value in the query string if it is
NOT the default setting.
For example, if you have a $page property to track pagination in a component, you may want to
remove the page property from the query string when the user is on the first page.
For example, if you want to shorten the URL, where the page property is represented as p and
search as s, you can use the as modifier to achieve that outcome.
Now the URL can look like this:
?s=Livewire%20is%20awesome&p=2
AUTHORIZATION
Introduction
To authorize actions in Livewire, you can use the AuthorizesRequests trait in any component,
then call $this->authorize() like you normally would inside a controller. For example:
If you use a different guard to authenticate your users then also add an entry to middleware_group
in the livewire config file:
PAGINATION
Introduction
Livewire offers the ability to paginate results within a component. This feature hooks into Laravel's
native pagination features, so it should feel like an invisible feature to you.
Paginating Data
Let's say you have a show-posts component, but you want to limit the results to 10 posts per page.
You can paginate the results by using the WithPagination trait provided by Livewire.
Now there will be rendered HTML links for the different pages at the bottom of your posts, and
the results will be paginated.
This method can be used in combination with the updating/updated lifecycle hooks to reset the
page when certain component data is updated.
An optional page name parameter may be passed through, if the pagination name is set to anything
other than page.
Multiple paginators on the same page
Because Livewire hardcodes the $page property inside the WithPagination trait, there is no way
to have two different paginators on the same page because each will be competing for the same
property name in the query string of the URL bar.
Here’s an example of two different components that might exist on the same page. By giving the
second one (the comments one) a name, Livewire will pick it up and handle everything
accordingly.
Now in the query string, both paginators will be represented like so:
To reset a specific paginator, you may pass through your custom page name using the -
>resetPage() method as found in the WithPagination trait.
Unfortunately, Livewire will overwrite a custom view you have defined inside a service
provider using: Paginator::defaultView().
When using either method, instead of anchor tags in your pagination component, you should use
wire:click handlers with the following methods:
Introduction
You may want to redirect from inside a Livewire component to another page in your app. Livewire
supports the standard redirect response syntax you are used to using in Laravel controller.
Now, after the user clicks "Submit" and their contact is added to the database, they will be
redirected to the success page (/contact-form-success).
Because Livewire works with Laravel's redirection system, you can use any notation
you are used to like redirect('/foo'), redirect()->to('/foo'), redirect()-
>route('foo').
FLASH MESSAGES
Introduction
In cases where it's useful to "flash" a success or failure message to the user, Livewire supports
Laravel's system for flashing data to the session.
If you wish to add flash data to a redirect and show the message on the destination page instead,
Livewire is smart enough to persist the flash data for one more request. For example:
Now when a user "Saves" a post, they will be redirected to the "/posts" endpoint and see the flash
message there. This assumes the /posts page has the proper Blade snippet to display flash
messages.
TRAITS
Introduction
PHP Traits are a great way to re-use functionality between multiple Livewire components.
For example, you might have multiple "data table" components in your application that all share
the same logic surrounding sorting.
LOADING STATES
Introduction
Because Livewire makes a roundtrip to the server every time an action is triggered on the page,
there are cases when the page may not react immediately to a user event (like a click). Livewire
allows you to easily display loading states, which can make your app feel more responsive.
When the "Checkout" button is clicked, the "Processing Payment..." message will show. When the
action is finished, the message will disappear.
By default, Livewire set's a loading element's "display" CSS property to "inline-block". If you
want Livewire to use "flex" or "grid", you can use the following modifiers.
You can also "hide" an element during a loading state using the .remove modifier.
If you wish, you can customize the delay duration with the following modifiers:
Targeting specific actions
The method outlined above works well for simple components. For more complex components,
you may want to show loading indicators only for specific actions.
In the above example, the loading indicator will be displayed when the "Checkout" button is
clicked, but not when the "Cancel" button is clicked.
wire:target can accept multiple arguments in a comma separated format like this:
wire:target="foo, bar".
If you wish to trigger a loading indicator when ANY of the properties of an array change, you can
simply target the entire array:
Targeting models
In addition to actions, you can also target whenever a wire:model is synchronized.
Toggling classes
You can add or remove classes from an element during loading states, by adding the .class
modifier to the wire:loading directive.
Now, when the "Checkout" button is clicked, the background will turn gray while the network
request is processing.
You can also perform the inverse and remove classes by adding the .remove modifier.
Now the bg-blue class will be removed from the button while loading.
Toggling attributes
Similar to classes, HTML attributes can be added or removed from elements during loading states:
Now, when the "Checkout" button is clicked, the disabled="true" attribute will be added to the
element while loading.
POLLING
Introduction
Livewire offers a directive called wire:poll that, when added to an element, will refresh the
component every 2s.
Polling for changes over Ajax is a lightweight, simpler alternative to something like
Laravel Echo, Pusher, or any WebSocket strategy.
You can customize the frequency by passing a directive modifier like 750ms. For example:
You can also specify a specific action to fire on the polling interval by passing a value to
wire:poll:
Now, the foo method on the component will be called every 2 seconds.
Polling in the background
Livewire reduces polling when the browser tab is in the background so that it doesn't bog down
the server with ajax requests unnecessarily. Only about 5% of the expected polling requests are
kept.
If you'd like to keep polling at the normal rate even while the tab is in the background, you can use
the keep-alive modifier:
Introduction
Livewire offers the ability to "prefetch" the result of an action on mouseover. Toggling display
content is a common use case.
This is useful for cases when an action DOES NOT (like writing to session or
database) perform side effects. If the action you are "pre-fetching" has side-effects,
the side-effects will be unpredictably executed.
Now, when the mouse enters the "Show Content" button, Livewire will fetch the result of the
"toggleContent" action in the background. If the button is actually clicked, it will display the
content on the page without sending another network request. If the button is NOT clicked, the
prefetched response will be thrown away.
OFFLINE STATE
Introduction
It's sometimes important to notify a user if they have lost their internet connection. Livewire
provides helpful utilities to perform actions based on a user's "offline" state.
Toggling elements
You can show an element on the page when the user goes "offline", by adding the wire:offline
attribute.
This <div> will automatically be hidden by default, and shown to the user when the browser goes
offline.
Toggling classes
Adding the class modifier allows you to add a class to an element when "offline".
Now, when the browser goes offline, the element will receive the bg-red-300 class. The class will
be removed again once the user is back online.
You can also perform the inverse, and remove classes by adding the .remove modifier, similar to
how wire:loading works.
The bg-green-300 class will be removed from the <div> while offline.
Toggling attributes
Adding the attr modifier allows you to add an attribute to an element when "offline".
Now, when the browser goes offline, the button will be disabled.
You can also perform the inverse, and remove attributes by adding the .remove modifier.
DIRTY STATES
Introduction
There are cases where it may be useful to provide feedback that content has changed and is not yet
in-sync with the back-end Livewire component.
For input that uses wire:model, or wire:model.lazy, you may want to display that a field is
'dirty' until Livewire has fully updated.
Adding the class modifier allows you to add a class to the element when dirty.
Now, when a user modifies the input value, the element will receive the border-red-500 class.
The class will be removed again if the input value returns to its original state, or if the Livewire
component updates.
You can also perform the inverse, and remove classes by adding the .remove modifier, similar to
how wire:loading works.
The bg-green-200 class will be removed from the input while dirty.
Toggling elements
The default behaviour of the wire:dirty directive without modifiers is that the element will be
hidden until dirty. This can create a paradox if used on the input itself, but like loading states, the
dirty directive can be used to toggle the appearance of other elements using wire:target.
In this example, the span will be hidden by default, and only visible when the input element is
dirty.
Now, when the input is dirty, the label text will receive the text-red-500 class.
DEFER LOADING
Introduction
Livewire offers a wire:init directive to run an action as soon as the component is rendered. This
can be helpful in cases where you don't want to hold up the entire page load, but want to load some
data immediately after the page load.
The loadPosts action will be run immediately after the Livewire component renders on the page.
JS INTEGRATIONS
ALPINEJS
Introduction
There are lots of instances where a page interaction doesn't warrant a full server-roundtrip, like
toggling a modal.
It allows you to sprinkle JavaScript behavior directly into your markup in a declarative/reactive
way that should feel very similar to VueJS (If that's what you're used to).
Installation
You must install Alpine in order to use it with Livewire.
To install Alpine in your project, add the following script tag to the <head> section of your layout
file.
Because of this, when possible, you should extract the Alpine parts to reusable Blade components
for consumption inside of Livewire (and anywhere in your app).
Now, the Livewire and Alpine syntaxes are completely separate, AND you have a reusable Blade
component to use from other components.
Now, when a user clicks "Increment", the standard Livewire round trip will trigger and Alpine will
reflect Livewire's new $count value.
Because $wire uses a JavaScript Proxy under the hood, you are able to access properties on it and
call methods on it and those operations will be forwarded to Livewire. In addition to this
functionality, $wire also has standard, built-in methods available to you.
Now a user can toggle on the dropdown immediately with Alpine, but when they click a Livewire
action like "Archive", the dropdown will be told to close from Livewire. Both Alpine and Livewire
are welcome to manipulate their respective properties, and the other will automatically update.
Sometimes, it isn't necessary to update Livewire on every Alpine change, and you'd rather bundle
the change with the next Livewire request that goes out. In these cases, you can chain on a .defer
property like so:
Now, when a user toggles the dropdown open and closed, there will be no AJAX requests sent for
Livewire, HOWEVER, when a Livewire action is triggered from a button like "archive" or
"delete", the new state of "showDropdown" will be bundled along with the request.
If you are having trouble following this difference. Open your browser's devtools and observe the
difference in XHR requests with and without .defer added.
One difficulty you might encounter while implementing Blade components within a Livewire
context is accessing the value of attributes like wire:model from inside the component.
For example, you might create a text input Blade component like so:
A simple Blade component like this will work perfectly fine. Laravel and Blade will automatically
forward any extra attributes added to the component (like wire:model in this case), and place
them on the <input> tag because we echoed out the attribute bag ($attributes).
However, sometimes you might need to extract more detailed information about Livewire
attributes passed to the component.
For these cases, Livewire offers an $attributes->wire() method to help with these tasks.
You could access Livewire directive information from Blade's $attribute bag like so:
You can also "forward" these Livewire directives individually. For example:
There are LOTS of different ways to use this utility, but one common example is using it in
conjunction with the aforementioned @entangle directive:
Note: If the .defer modifier is passed via wire:model.defer, the @entangle directive will
automatically recognize it and add the @entangle('...').defer modifier under the hood.
Creating A DatePicker Component
A common use case for JavaScript inside Livewire is custom form inputs. Things like datepickers,
color-pickers, etc... are often essential to your app.
By using the same pattern above, (and adding some extra sauce), we can utilize Alpine to make
interacting with these types of JavaScript components a breeze.
Let's create a re-usable Blade component called date-picker that we can use to bind some data
to in Livewire using wire:model.
According to the docs, the most basic usage of the package (after including the assets) looks like
this:
All you need is an <input> element, and Pikaday will add all the extra date-picker behavior for
you.
Now let's see how we might write a re-usable Blade component for this library.
Note: The {{ $attributes }} expression is a mechanism in Laravel 7 and above to forward extra
HTML attributes declared on the component tag.
Let's create a contrived example where when a user clicks the first button a property called $foo
is set to bar, and when a user clicks the second button, $foo is set to baz.
For the component definition, we will be using a third-party color-picker lib called Vanilla Picker.
When this happens, it's hard for Livewire to keep track of what DOM manipulations you want to
preserve on component updates, and which you want to discard.
To tell Livewire to ignore changes to a subset of HTML within your component, you can add the
wire:ignore directive.
The Select2 library is one of those libraries that takes over its portion of the DOM (it replaces your
<select> tag with lots of custom markup).
Here is an example of using the Select2 library inside a Livewire component to demonstrate the
usage of wire:ignore.
Also, note that sometimes it's useful to ignore changes to an element, but not its
children. If this is the case, you can add the self modifier to the wire:ignore
directive, like so: wire:ignore.self.
LARAVEL ECHO
Introduction
Livewire pairs nicely with Laravel Echo to provide real-time functionality on your web-pages
using WebSockets.
This feature assumes you have installed Laravel Echo and the `window.Echo` object is
globally available. For more info on this, check out the docs.
Let's say you fire this event with Laravel's broadcasting system like this:
Normally, you would listen for this event in Laravel Echo like so:
Listeners
With Livewire all you have to do is register it in your $listeners property, with some special
syntax to designate that it originates from Echo.
If you have Echo channels with variables in (such as a Order ID) you can use the getListeners()
function instead of the $listeners array.
getListeners() will only dynamically generate the names of listeners when the
component is mounted. Once the listeners are setup, these can't be changed.
Now, Livewire will intercept the received event from Pusher, and act accordingly.
Introduction
Livewire recommends that you use AlpineJS for most of your JavaScript needs, but it does support
using <script> tags directly inside your component's view.
Please note that your scripts will be run only once upon the first render of the
component. If you need to run a JavaScript function later - emit the event from the
component and listen to it in JavaScript as described here)
You can also push scripts directly onto Blade stacks from your Livewire component:
Here's an example:
Note: the @this directive compiles to the following string for JavaScript to interpret:
"Livewire.find([component-id])"
TESTING
Introduction
Livewire offers a powerful set of tools for testing your components.
Alternatively, you may pass a component's class name to the assertSeeLivewire and
assertDontSeeLivewire methods.
Testing With Query String Parameters
To test Livewire's $queryString functionality, you can use Livewire's ::withQueryParams
testing utility.
Testing Components With Passed Data
Generating Tests
When creating a component, you can include the --test flag, and a test file will be created for
you as well.
All Available Test Methods
DEPLOYMENT
Livewire Changes
Occasionally there will be changes to Livewire's internal method signatures that will require a
refresh of any components currently running in the browser (we try to keep these to a minimum).
To achieve this, Livewire uses an internal deployment hash and keeps track of whether it has
changed or not.
If Livewire's deployment hash has changed, it will trigger the page expired dialog or hook.
You could dispatch a browser event from the page expired callback, that Alpine could
listen for to show a custom dialog modal prompting users to refresh their page.
You need to either place the Livewire.onPageExpired() call after Livewire's scripts in your
layout file
Introduction
To the new Livewire developer, the experience is somewhat magical. It feels as if when the page
loads, your Livewire component is living on a server listening for updates from the browser and
responding to them in real-time.
This is not far from how other, similar tools like Phoenix LiveView work.
However much Livewire feels similar, it has quite different inner-workings that have their own
sets of pros, cons, and security implications.
Livewire components feel "stateFULL", however, they are completely "stateLESS". There is no
long-running Livewire instance on the server waiting for browser interactions. Each interaction is
an entirely new and fresh request/response.
To more fully grasp this mental model, let's use the following simple "counter" component as a
starting point.
The experience of using this "counter" from a user's perspective goes like this: A user loads the
page, sees the number "1", clicks the "+" button, and now sees the number "2".
Now that the front-end has the component state, when an update is triggered (clicking the "+" in
this case), a request is sent to the server INCLUDING the last-known component state. The server
"hydrates" or "deserializes" the component from that state and performs any updates.
The component is now dehydrated again to provide the browser with the newly rendered HTML
and the updated state for use in later interactions requests.
Here is a deeper visualization of the actual component lifecycles during these requests.
Hopefully now you've adopted a more accurate mental model of how Livewire works under the
hood. This will allow you to more intelligently debug problems and understand the performance
and security implications of using Livewire.
Security Measures
Like you learned above, each Livewire request is "stateless" in the sense that there is no long-
running server instance maintaining state. The state is stored in the browser and passed back and
forth to the server between requests.
Because the state is stored in the browser, it is vulnerable to front-end manipulation. Without
security measures in place, it would not be difficult for a malicous person to manipulate the state
of a component in the browser between requests.
In our "counter" example, there are no real negative implications of manipulating something as
trivial and ephemeral as the "count" of that component, but in a component with more at stake, for
example an "edit post" component with a delete button, security measures need to be in place.
The Checksum
The fundamental security underpinning Livewire is a "checksum" that travels along with
request/responses and is used to validate that the state from the server hasn't been tampered with
in the browser.
o further explain, consider the "counter" component above. Rather than simply passing { count:
1 } to the browser, Livewire will generate a hash (checksum) of that payload using a secure key
and pass it along with the state.
A more realistic representation of the Livewire payload for the "counter" would look something
like this:
Now if a malicous person tampered with the state in the browser between requests, before Livewire
handled a component update, it would see that a hash of the payload doesn't match the checksum
and throw an error.
Persistent Middleware
The second security measure Livewire puts in place is "persistent middleware". This means
Livewire will capture any authentication/authorization middleware that was used during the
"Initial Request" and re-apply it to subsequent requests.
Without this measure, a Livewire subsequent request could be captured and re-played after a user
has been logged out of the application and should no longer have access to those code paths.
If you wish to add your own middlewares to be captured and re-applied if present, you can do so
in your app's service provider with the following API:
Now any middlewares you added will be re-applied to subsequent Livewire requests IF the
middleware is assigned to the original route the component was loaded on.
TROUBLESHOOTING
For the most part, this system is reliable, but there are certain cases where Livewire is unable to
properly track changes. When this happens, hopefully, a helpful error will be thrown and you can
debug with the following guide.
Symptoms
• An input element loses focus
• An element or group of elements dissapears suddenly
• A previously interactive element stops responding to user input
• A loading indicator mis-fires
• A user action no longer functions
Cures
Ensure your component has a single-level root element
Add wire:key to elements inside loops (the value to wire:key must be unique across the page):
Add wire:key. As a final measure, adding wire:key will directly tell Livewire how to keep track
of a DOM element. Over-using this attribute is a smell, but it is very useful and powerful for
problems of this nature.
The value you pass to wire:key must be entirely unique to that page. Meaning that
you should prefix it, like wire:key="item-{{ $item->id }}", and avoid using
$loop->index to track the individual elements where you can.
Checksum Issues
On every request, Livewire does a "checksum" but in some cases with arrays, it can throw an
exception even when the data inside the array is the same.
Because in PHP an array can have keys that are alpha-numeric and numeric keys in the same array
and in any order, but Javascript will make an object of it because it doesn't support arrays with
keys that are alpha-numeric. When Javascript is creating an object it will also reorder the keys, it
will place numeric keys before alpha-numeric keys.
This causes a problem when the JSON is sent back because the "checksum" will look different.
Some types (Point, LineString, Polygon, and the Multi- variations) will also fail this checksum.
So make sure when you have a public property that is an array numeric keys are before alpha-
numeric character keys.
Symptoms
• The query string does not get updated at all.
• The query string does not get updated when the value is empty.
Cures
If you do set security headers, make sure the referrer-policy value is set to same-origin.
Root Element Issues
Livewire requires that there be only one HTML element at the root of a components blade view.
Having multiple root elements can mean that parts of your view won't work with Livewire
correctly, if at all.
Symptoms
A button isn't triggering a wire:click
Parts of your view aren't updating properly (could also be a Dom Diffing issue, see above)
You get an error in your browser console that says Livewire: Multiple root elements
detected. This is not supported.
See below for an example of a component with a button that doesn't work:
Cures
The solution is to ensure that you only have one root HTML element, such as a <div>. If you have
multiple elements, then wrap everything in a <div> or another element that suits your layout.
So in our example from above, we have wrapped everything in a <div> which gets the button
running:
Another cause can be using __construct() inside the Livewire class or a Trait.
PACKAGE DEVELOPMENT
Now, applications with your package installed can consume your component in their views like
so:
ARTISAN COMMANDS
Once created, you can render your components in a Blade file with the @livewire('component-
name') blade directive.
Think of Livewire components like Blade includes. You can insert @livewire anywhere in a Blade
view and it will render.
If you are on Laravel 7 or greater, you can use the tag syntax.
Modifying Stubs
You can customize the stubs (templates) that Livewire uses to create new component classes and
views using the livewire:stubs command.
stubs/livewire.view.stub
stubs/livewire.inline.stub
Now, when you run the make:livewire command, Livewire will use the above stub files as the
template.
Introduction
At Livewire we appreciate and welcome all contributions!
If that's something you would be interested in doing, we recommend going through this
contribution guide first before starting.
Fork Livewire
Go to the Livewire repository on GitHub and fork the Livewire repository.
Install dependencies
Install composer dependencies by running:
To get orchestral/testbench-dusk to run, you need to install the latest chrome driver by
running:
Run tests
Once everything is configured, run all tests to make sure everything is working and passing.
If the dusk tests don't run and you get an error, make sure you have run the command in the
Configure dusk section above.
If you still get an error, the first time you try to run dusk tests, you may also need to close any
Google Chrome instances you may have open and try running the tests again. After that, you should
be able to leave Chrome open when running tests.
Do not use your master/ main branch of your fork as maintainers cannot modify PR's submitted
from a master/main branch on a fork.
Livewire has both Dusk browser tests and standard PHPUnit unit tests, which you can find in
tests/Browser and tests/Unit respectively.
Livewire runs both PHP and Javascript code, so Dusk browser tests are preferred to ensure
everything works as expected, and can be supported with unit tests as required.
See below for an example of how a Livewire Dusk test should be structured:
You can see how to use Dusk in the Laravel documentation as well as look at Livewire's existing
browser tests for further examples.
Change the code as required to fix the bug or add the new feature, but try to keep changes to a
minimum. Consider splitting into multiple PR's if required.
PR's that make too many changes or make unrelated changes may be closed.
If you have updated any of Livewire's javascript code, you will need to recompile the assets. To
do this run npm run build, or you may start a watcher with npm run watch.
If you update any javascript, make sure to recompile assets and commit them.
Once you have finished writing your code, do a review to ensure you haven't left any debugging
code and formatting matches the existing style.
Run tests
The final step before submitting is to run all tests to ensure your changes haven't impacted anything
else.
If the Dusk browser tests don't run, see Run tests in the Setup section above for more details
Submit PR
Once all tests pass, then push your branch up to GitHub and submit your PR.
In your PR description make sure to provide a small example of what your PR does along with a
thorough description of the improvement and reasons why it's useful. Add links to any issues or
discussions that are relevant for further details.
For first-time contributors, tests won't run automatically, so they will need to be started
by a maintainer.