Properties
- Introduction
- Initializing Properties
- Data Binding
- Updating The Query String
- Casting Properties
- Computed Properties
Public Properties
Livewire components store and track data as public properties on the component class.
1class HelloWorld extends Component2{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).
1use Livewire\Component; 2 3class HelloWorld extends Component 4{ 5 public $message = 'Hello World!'; 6 7 public function render() 8 { 9 return view('livewire.hello-world');10 }11}
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:
- Data stored in public properties is made visible to the front-end JavaScript. Therefore, you SHOULD NOT store sensitive data in them.
- Properties can ONLY be either a JavaScript-friendly data types (
string
,int
,array
,boolean
), OR an eloquent model (or collection of models). To use properties with other data types, you must pass each through a custom caster. - For PHP >= 7.4 users: public properties in Livewire components DO NOT currently support typed properties.
protected
and private
properties DO NOT persist between Livewire updates. In general, you should avoid using them for storing state.
Initializing Properties
You can initialize properties using the mount
method of your component.
1use Livewire\Component; 2 3class HelloWorld extends Component 4{ 5 public $message; 6 7 public function mount() 8 { 9 $this->message = 'Hello World!';10 }11 12 public function render()13 {14 return view('livewire.hello-world');15 }16}
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}
You can even pass $this->fill()
an Eloquent model. When you do, public properties in your Livewire component that match properties included in your Eloquent model's toArray()
method
will be filled.
1public function mount(User $user)2{3 $this->fill($user);4}
Additionally, Livewire offers $this->reset()
to programatically reset public property values to their initial state. This is useful for cleaning input fields after performing an action.
1public $name = ''; 2public $content = ''; 3 4public function savePost() 5{ 6 $this->post->update([ 7 'name' => $this->name, 8 'content' => $this->content, 9 ]);10 11 $this->reset();12 // Will reset all public properties.13 14 $this->reset('name');15 // Will only reset the name property.16 17 $this->reset(['name', 'content']);18 // Will reset both the name AND the content property.19}
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.
1use Livewire\Component; 2 3class HelloWorld extends Component 4{ 5 public $message; 6 7 public function render() 8 { 9 return view('livewire.hello-world');10 }11}
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.
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> |
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">
Binding Nested Data
Livewire supports binding to nested data inside arrays using dot notation:
1<input type="text" wire:model="parent.message">
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.
Updating The Query String
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 $updatesQueryString
, and Livewire will update the query string every time the property value changes.
1use Livewire\Component; 2 3class SearchPosts extends Component 4{ 5 public $search; 6 7 protected $updatesQueryString = ['search']; 8 9 public function mount()10 {11 $this->search = request()->query('search', $this->search);12 }13 14 public function render()15 {16 return view('livewire.search-posts', [17 'posts' => Post::where('title', 'like', '%'.$this->search.'%')->get(),18 ]);19 }20}
1<div> 2 <input wire:model="search" type="text" placeholder="Search posts by title..."> 3 4 <h1>Search Results:</h1> 5 6 <ul> 7 @foreach($posts as $post) 8 <li>{{ $post->title }}</li> 9 @endforeach10 </ul>11</div>
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.
In cases like these, you can use the following syntax:
1use Livewire\Component; 2 3class SearchPosts extends Component 4{ 5 public $foo; 6 public $search = ''; 7 public $page = 1; 8 9 protected $updatesQueryString = [10 'foo',11 'search' => ['except' => ''],12 'page' => ['except' => 1],13 ];14 15 public function mount()16 {17 $this->fill(request()->only('search', 'page'));18 }19 20 ...21}
Casting Properties
Livewire offers an api to "cast" public properties to a more usable data type. Two common use-cases for this are working with date objects like Carbon
instances, and dealing with Laravel collections:
1class CastedComponent extends Component 2{ 3 public $options; 4 public $expiresAt; 5 public $formattedDate; 6 7 protected $casts = [ 8 'options' => 'collection', 9 'expiresAt' => 'date',10 'formattedDate' => 'date:m-d-y'11 ];12 13 public function mount()14 {15 $this->options = collect(['foo', 'bar', 'bar']);16 $this->expiresAt = \Carbon\Carbon::parse('tomorrow');17 $this->formattedDate = \Carbon\Carbon::parse('today');18 }19 20 public function getUniqueOptions()21 {22 return $this->options->unique();23 }24 25 public function getExpirationDateForHumans()26 {27 return $this->expiresAt->format('m/d/Y');28 }29 30 ...
Custom Casters
Livewire allows you to build your own custom casters for custom use-cases. Implement the Livewire\Castable
interface in a class and reference it in the $casts
property:
1class FooComponent extends Component2{3 public $foo = ['bar', 'baz'];4 5 protected $casts = ['foo' => CollectionCaster::class];6 7 ...
1use Livewire\Castable; 2 3class CollectionCaster implements Castable 4{ 5 public function cast($value) 6 { 7 return collect($value); 8 } 9 10 public function uncast($value)11 {12 return $value->all();13 }14}
Custom casters are especially useful when you are attempting to store unsupported data types within properties.
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 Component2{3 // Computed Property4 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:
1use Livewire\Component; 2 3class ShowPost extends Component 4{ 5 public $postId; 6 7 public function mount($postId) 8 { 9 $this->postId = $postId;10 }11 12 public function getPostProperty()13 {14 return Post::find($this->postId);15 }16 17 public function deletePost()18 {19 $this->post->delete();20 }21 22 public function render()23 {24 return view('livewire.show-post');25 }26}
1<div>2 <h1>{{ $this->post->title }}</h1>3 ...4 <button wire:click="deletePost">Delete Post</button>5</div>