You're browsing the documentation for an old version of Livewire. Consider upgrading your project to Livewire 3.x.

Properties

Be amazing at Livewire
with our in-depth screencasts.
Watch Now

Introduction

Livewire components store and track data as public properties on the component class.

        
1class HelloWorld extends Component
2{
3 public $message = 'Hello World!';
4 ...

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).

            
1class HelloWorld extends Component
2{
3 public $message = 'Hello World!';
4}
            
1<div>
2 <h1>{{ $message }}</h1>
3 <!-- Will output "Hello World!" -->
4</div>

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.
protected and private properties DO NOT persist between Livewire updates. In general, you should avoid using them for storing state.
You should also note that while null data type is Javascript-friendly, public properties set to null DO NOT persist between Livewire updates.

Initializing Properties

You can initialize properties using the mount method of your component.

            
1class HelloWorld extends Component
2{
3 public $message;
4 
5 public function mount()
6 {
7 $this->message = 'Hello World!';
8 }
9}

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.

            
1public function mount()
2{
3 $this->fill(['message' => 'Hello World!']);
4}

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.

            
1public $search = '';
2public $isActive = true;
3 
4public function resetFilters()
5{
6 $this->reset('search');
7 // Will only reset the search property.
8 
9 $this->reset(['search', 'isActive']);
10 // Will reset both the search AND the isActive property.
11 
12 $this->resetExcept('search');
13 // Will only reset the isActive property (any property but the search property).
14}

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.

            
1class HelloWorld extends Component
2{
3 public $message;
4}
            
1<div>
2 <input wire:model="message" type="text">
3 
4 <h1>{{ $message }}</h1>
5</div>

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.

Common elements to use wire:model on include:

Element Tag
<input type="text">
<input type="radio">
<input type="checkbox">
<select>
<textarea>

Binding Nested Data

Livewire supports binding to nested data inside arrays using dot notation:

        
1<input type="text" wire:model="parent.message">

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:

        
1<input type="text" wire:model.debounce.500ms="name">

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.

        
1<input type="text" wire:model.lazy="message">

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.

For example, given the following component:

        
1<input type="text" wire:model.defer="query">
2<button wire:click="search">Search</button>

As the user types into the <input> field, no network requests will be sent. Even if the user clicks away from the input field and onto other fields on the page, no requests will be sent.

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.

Binding Directly To Model Properties

If an Eloquent model is stored as a public property on a Livewire component, you can bind to its properties directly. Here is an example component:

            
1use App\Post;
2 
3class PostForm extends Component
4{
5 public Post $post;
6 
7 protected $rules = [
8 'post.title' => 'required|string|min:6',
9 'post.content' => 'required|string|max:500',
10 ];
11 
12 public function save()
13 {
14 $this->validate();
15 
16 $this->post->save();
17 }
18}
            
1<form wire:submit.prevent="save">
2 <input type="text" wire:model="post.title">
3 
4 <textarea wire:model="post.content"></textarea>
5 
6 <button type="submit">Save</button>
7</form>

Notice in the above component we are binding directly to the "title" and "content" model attributes. Livewire will take care of hydrating and dehydrating the model between requests with the current, non-persisted data.

Note: For this to work, you need to have a validation entry in the `$rules` property for any model attributes you want to bind to. Otherwise, an error will be thrown.

Additionally, you can bind to models within an Eloquent Collection.

            
1use App\Post;
2 
3class PostForm extends Component
4{
5 public $posts;
6 
7 protected $rules = [
8 'posts.*.title' => 'required|string|min:6',
9 'posts.*.content' => 'required|string|max:500',
10 ];
11 
12 public function mount()
13 {
14 $this->posts = auth()->user()->posts;
15 }
16 
17 public function save()
18 {
19 $this->validate();
20 
21 foreach ($this->posts as $post) {
22 $post->save();
23 }
24 }
25}
            
1<form wire:submit.prevent="save">
2 @foreach ($posts as $index => $post)
3 <div wire:key="post-field-{{ $post->id }}">
4 <input type="text" wire:model="posts.{{ $index }}.title">
5 
6 <textarea wire:model="posts.{{ $index }}.content"></textarea>
7 </div>
8 @endforeach
9 
10 <button type="submit">Save</button>
11</form>

Livewire also supports binding to relationships on Eloquent models like so:

            
1class EditUsersPosts extends Component
2{
3 public User $user;
4 
5 protected $rules = [
6 'user.posts.*.title'
7 ];
8 
9 public function save()
10 {
11 $this->validate();
12 
13 $this->user->posts->each->save();
14 }
15}
            
1<div>
2 @foreach ($user->posts as $i => $post)
3 <input type="text" wire:model="user.posts.{{ $i }}.title" />
4 
5 <span class="error">
6 @error('user.posts.'.$i.'.title') {{ $message }} @enderror
7 </span>
8 @endforeach
9 
10 <button wire:click="save">Save</button>
11</div>

Custom (Wireable) Properties

Sometimes you may want to set a component property to a non-model object that's available inside your app, like a DTO (Data Transfer Object).

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:

            
1class Settings implements Livewire\Wireable
2{
3 public $items = [];
4 
5 public function __construct($items)
6 {
7 $this->items = $items;
8 }
9 
10 ...
11 
12 public function toLivewire()
13 {
14 return $this->items;
15 }
16 
17 public static function fromLivewire($value)
18 {
19 return new static($value);
20 }
21}

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 typehinted like so:

            
1class SettingsComponent extends Livewire\Component
2{
3 public Settings $settings;
4 
5 public function mount()
6 {
7 $this->settings = new Settings([
8 'foo' => 'bar',
9 ]);
10 }
11 
12 public function changeSetting()
13 {
14 $this->settings->foo = 'baz';
15 }
16}

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.

        
1class ShowPost extends Component
2{
3 // Computed Property
4 public function getPostProperty()
5 {
6 return Post::find($this->postId);
7 }

Now, you can access $this->post from either the component's class or Blade view:

            
1class ShowPost extends Component
2{
3 public $postId;
4 
5 public function getPostProperty()
6 {
7 return Post::find($this->postId);
8 }
9 
10 public function deletePost()
11 {
12 $this->post->delete();
13 }
14}
            
1<div>
2 <h1>{{ $this->post->title }}</h1>
3 ...
4 <button wire:click="deletePost">Delete Post</button>
5</div>
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.
← Previous Topic Rendering Components
Next Topic → Actions