There are a lot of cases where one Livewire component needs to communicate with another. In this lesson, let's see how it is done using Events.
In this example, we will have a Livewire component for showing a post and another component for posting a comment. When a comment is posted, the comment count in the ViewPost
Livewire component should be updated.
DB structure: the Comment
Model only has the post_id
and body
fields. And we need a comments()
relationship in the Post
Model.
database/migrations/xxxx_create_comments_table.php:
Schema::create('comments', function (Blueprint $table) { $table->id(); $table->foreignId('post_id'); $table->string('body'); $table->timestamps();});
app/Models/Post.php:
use Illuminate\Database\Eloquent\Relations\HasMany; class Post extends Model{ protected $fillable = [ 'title', 'body', ]; public function comments(): HasMany { return $this->hasMany(Comment::class); } }
And here is the initial Livewire components.
app/Livewire/ViewPost.php:
use App\Models\Post;use Illuminate\Contracts\View\View; class ViewPost extends Component{ public Post $post; public int $commentsCount = 0; public function mount(Post $post): void { $this->post = $post; $this->post->loadCount('comments'); $this->commentsCount = $this->post->comments_count; } public function render(): View { return view('livewire.view-post'); }}
resources/views/livewire/view-post.php:
<div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg"> <div class="p-6 text-gray-900 dark:text-gray-100"> <h1 class="text-lg font-bold mb-4">{{ $post->title }}</h1> <p>Comments: {{ $commentsCount }}</p> <livewire:create-comment :post="$post" /> </div> </div> </div></div>
app/Livewire/CreateComment.php:
use App\Models\Post;use Livewire\Component;use Livewire\Attributes\Validate;use Illuminate\Contracts\View\View; class CreateComment extends Component{ public Post $post; #[Validate('required')] public string $body = ''; public function save(): void { $this->validate(); $this->post->comments()->create(['body' => $this->body]); $this->reset('body'); } public function render(): View { return view('livewire.create-comment'); }}
Notice: As you can see in the
CreateComment
Livewire component, nomount()
method exists. This is another alternative to reduce code. Livewire automatically sets$post
to the correct Post from the Route Model Binding.
resources/views/livewire/create-comment.php:
<div class="mt-4"> <form method="POST" wire:submit="save"> <div> <label for="body" class="block font-medium text-sm text-gray-700">Body</label> <textarea id="body" wire:model="body" class="block mt-1 w-full border-gray-300 rounded-md shadow-sm"></textarea> @error('body') <span class="mt-2 text-sm text-red-600">{{ $message }}</span> @enderror </div> <button class="mt-4 px-4 py-2 bg-gray-800 rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700"> Save </button> </form></div>
I will use it as a full-page Livewire component, so the Route would look like this.
routes/web.php:
Route::get('post/{post}', \App\Livewire\ViewPost::class);
After visiting the page, we have a similar result to the one below:
After saving the comment, we need to trigger an event. This is done using the dispatch()
method and passing the event's name.
app/Livewire/CreateComment.php:
class CreateComment extends Component{ // ... public function save(): void { $this->post->comments()->create(['body' => $this->body]); $this->dispatch('comment-added'); $this->reset('body'); } // ...}
Notice: in the older Livewire v2, the method name was called
->emit()
, in v3 it was changed to->dispatch()
.
Now that event is triggered, we must listen for it in the ViewPost
Livewire component. To do that, we need to add a #[On]
attribute above the method that needs to be called.
app/Livewire/ViewPost.php:
use Livewire\Attributes\On; class ViewPost extends Component{ // ... #[On('comment-added')] public function commentAdded(): void { $this->commentsCount++; } // ...}
After saving the comment now, the comments count is incremented.
So, that's how you communicate between Livewire components: your page may consist of many individual smaller components, passing data between each other by dispatching events.