Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

valentin_vranic's avatar

Livewire3 dynamic event handlers

Can someone please provide me an example how to dispatch and how to listen with #[On('event')] properly with dynamic event?

I've checked in docs, but I'm not sure am I getting it right!

    #[On('post-updated.{post.id}')] 
    public function refreshPost()
    {
        // ...
    }

The {post.id}' is supposed to be an exact id? Or it can somehow bind it with the public $post property?

Thanks!

0 likes
6 replies
LaryAI's avatar
Level 58

To handle dynamic event listeners in Livewire 3 using the #[On('event')] attribute, you can indeed bind dynamic parts of the event name to properties of your Livewire component. Here's a step-by-step example to illustrate how you can achieve this:

  1. Define the Event Listener with Dynamic Binding:

    You can use the #[On('event')] attribute to listen for events dynamically. The dynamic part of the event name can be bound to a property of your Livewire component.

    use Livewire\Component;
    use Livewire\Attributes\On;
    
    class PostComponent extends Component
    {
        public $post;
    
        public function mount($post)
        {
            $this->post = $post;
        }
    
        #[On('post-updated.{post.id}')]
        public function refreshPost()
        {
            // Logic to refresh the post
            $this->post->refresh();
        }
    
        public function render()
        {
            return view('livewire.post-component', ['post' => $this->post]);
        }
    }
    

    In this example, post.id is dynamically replaced with the id of the $post property.

  2. Dispatching the Event:

    When you want to dispatch the event, you need to ensure that the event name matches the dynamic pattern you defined in the listener.

    // Somewhere in your application, e.g., in another Livewire component or a controller
    $postId = 1; // Example post ID
    $post = Post::find($postId);
    
    // Dispatch the event
    event('post-updated.' . $post->id);
    
  3. Example Blade View:

    Here’s an example of how your Blade view might look:

    <!-- resources/views/livewire/post-component.blade.php -->
    <div>
        <h1>{{ $post->title }}</h1>
        <p>{{ $post->content }}</p>
    </div>
    

Explanation:

  • Dynamic Event Binding: The #[On('post-updated.{post.id}')] attribute listens for the post-updated event with the specific post ID. The {post.id} part is dynamically replaced with the id of the $post property.
  • Event Dispatching: When dispatching the event, ensure the event name includes the specific post ID, so it matches the pattern defined in the listener.

This approach allows you to dynamically bind event listeners to specific instances of your Livewire component, making it more flexible and powerful.

Chingy's avatar

Hi @valentin_vranic,

Imagine you have an index of posts, and each post is a LW component. If you want the parent (the index page) emit an event to a specific component you can do

$this->dispatch('postComponent.{$id}'); // or
$this->dispatch('postComponent'.$id);

You do not do $dispatch()->to. On your post component, if your property Post is public, you can do as per the docs and you will listen that event only for that specific component

valentin_vranic's avatar

@Chingy thanks for your reply (was on vacation)

And on child component, how do I listen to this dynamically dispatched event from parent?

    #[On('post-updated.{post.id}')] 
    public function refreshPost()
    {
        // ...
    }

?

Rather, one another question, related to this. Because what I want to achieve is that I have a list of posts where are related comments too. I'm working with wire:poll (polling each second, a specific method) because I want to display the comments related to the posts, and either the posts and comments are coming from another application to the database, I'm only trying to display them.

And what I wanted to achieve is, getting all new comments based on datetime, which refreshes whenever there are new comments, and based on their newest date. And I'm doing this call on index page, where Post components are listed, and when I get new comments each second, I foreach them and want to dispatch an event only to that Posts component to where they belong and append them there.

Currently I'm doing something like this, which actually works (however it unfortunately doesn't refreshes only the given Post block, but all of them on the index page...)

#[On('commentsUpdated')]
    public function updateComments(Comments $comment): void
{
    if ($this->post->post_id === $comment->post_id) {
        $this->post->comments->push($comment);
}
Chingy's avatar

@valentin_vranic Yes, you listen to it as listed. I believe if it's either bound to a Model or an Array, it can get to retrieve nested values.

I am missing context, so why do you wanna wire:poll in the first place ? You can for sure use Laravel Echo if it aint such a hassle for you. Way better and performant solution and wont bog you down the moment your DB grows large..

I believe updateComments is a function of a Post.show component or smth like that. Well it's one way to do it how you have written it, but you can try doing

#[On('commentsUpdated.{post.id}')]

// and do on your index comp.
$this->dispatch('commentsUpdated.'.$post->id);

But again, wire:polling will re-query everything. Laravel echo will notify you of newer comments which you will just store in your Collection of comments and pass them around to their respective post.show components.

1 like
valentin_vranic's avatar

@Chingy yeah, frankly, why I'm using wire:poll is that each second I'm getting the newest comments and attach them to the posts, and make it live, without refreshing the page. But for some reason even if I only refresh the given post (append the new comment to it) it reload all the views too, and when I have more than let's say 10-20 posts and simultaneously the comments are coming it will eat all the memory, because I guess how livewire refreshes the components....

I never used before laravel echo, but I could make a try with it. But already I'm not sure can I connect it with livewire to make the functionality the same as before, to make it "live"

Chingy's avatar

@valentin_vranic Livewire has specifically doc for integrating for with Laravel Echo.

Regarding your whole updates, hypotheticall, LW3 changes ("morhps" the DOM, as per the docs) the rendered DOM wherever is needed and not the whole HTML.

You could lower the wire:poll to 5sec. Another improvement i would is, make the comments on each post component, a computed property that returns collection. You will only store the IDs of the comments in an array, and you will retrieve the collection of the comments via a whereIn(). Alongside with the dynamic event listening, only the components whose array of comments IDs change, will be updated. And the rest is cached.

If you use a public Collection property, you will bog down, as it hydrates and dehydrates everything per sec (!). Imagine having eager loaded records as well.

Please or to participate in this conversation.