Listening for broadcast events
Hi folks
Been working with filament for a little bit now and really enjoying it.
I’ve been building with Laravel since v4 now and really liking the productivity bump.
Anyhow there’s something I’m trying to wrap my head around on how to do “the filament way”.
Let’s assume I have a component (TextEntry, TextColumn etc). For that specific item I know while displaying it, I will be receiving a broadcast notification (say for example a list of processes running in the background and when the state of any changes, I fire an event)
Now this would be no mystery with just Laravel using Broastasting + echo.
Even in Livewire (which I’ve been using for a long time) it would not be an issue (setting up listeners to subscribe to Echo)
How would I got about doing this with one of the filament pages? (Say View or List page)
Would it be a custom page treated like a regular Livewire component?
Is maybe a custom Field or custom Entry?
Receiving these live updates (considering we have everything in the ecosystem even with Reverb coming out) seems like a common scenario but I can’t find a proper information on it
Thanks in advance to anyone that could help shed some light
29 Replies
Pages are livewire components if that helps. They can also do polling.
So listen however you need to then you should be able to update the form or whatever as needed.
Thank you @awcodes I got broadcasting (with Reverb) set up. echo.js is in place and i can subscrive to the user's private channel. I can receive events as well. I set up the broadcaster in the filament config and i can already see it is subscribes automatically to the authed user's channel (provided it exists in channels.php). This is all fine and dandy.
Glad you got it working. Kinda of the beauty of filament. It’s still all just laravel and livewire.
I am looking at this https://livewire.laravel.com/docs/events#real-time-events-using-laravel-echo and i've set up the listeners in the filament page (ViewSite in this case)
Laravel
Events | Laravel
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
The problem is i'm not getting anything on the filament side 😩 and i know that getListeners method is getting called
What do you mean by not getting anything on the filament side. The page is still a livewire component.
technically speaking i don't even need echo.js (the project is all Filament) so setting up the listeners should be all that is needed (echo.js was set up just as a sanity check).
Sounds like you might be listening for the event on the wrong thing. But I could be wrong.
The event is fired. I can see it in the queue. I can see it in the reverb debug window and i can even listen for it (outsite of filament in a plain blade file) by subscribing via javascript. The Livewire listener is set up (via getListeners) but the handler (method called handleGlobalCheckCompleted is not invoked).
In Filament panels, the page is the livewire component
That's clear and fine. I've got the listener set up in a ViewRecord type page, in this case View site. I know that Livewire
getListeners
is getting called. I can dd in it.Ok, so what is the actual issue? The listener is getting “heard”, so what is the actual expectation.
The listener is firing but what isn’t happening based on it firing?
The getListeners() method of the component is getting called. But the handler for the given event is not. So i know that GlobalCheckCompletedEvent is getting fired in the system but although the listener is registered, the handler
handleGlobalCheckCompleted
is never getting called. So either my syntax is wrong, i'm missing something, or GlobalCheckCompletedEvent is not making it in this component.
That's the point. The listener is not firing.It might be too late in the lifecycle.
Or too early
Huh.
Can you verify there is an authenticated user at the point the listener happens.?
Granted this might be outside the scope of filament. And more to do with the lifecycle of laravel. Just what is coming to mind presently without a full understanding of the app.
Yep. when getListeners() is called there is an authed user. The user's id (uuid in this case) is getting pulled correctly. That's the right name for the channel
I think more than laravel it might be livewire. https://livewire.laravel.com/docs/events#real-time-events-using-laravel-echo. I've used echo and Livewire a number of times before and this has been the m.o. since it appeared as a feature in 2.x
Laravel
Events | Laravel
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
Holy shit i got it
Entirely possible
I should stop doing these things at 3am
lol.
10 pm here. But yes.
The syntax is a bit different. For private channels it's
"echo-private:App.Models.User." . auth()->id() . ",GlobalCheckCompletedEvent" => 'handleGlobalCheckCompleted'
instead of "echo:App.Models.User." . auth()->id() . ",GlobalCheckCompletedEvent" => 'handleGlobalCheckCompleted'
Tomorrow i'm going to figure out how to actually get the listening done on a TextEntry or TextColumn level. This listener here was just to check the piping. But it guess since those are Livewire components as well i'm either going to have to somehow set the listener (i think here is a setListeners() method) when i set up the TextEntry/TextColumn on the injected $livewire or go ahead and define a custom TextEntry/TextColumn and add listening capabilities to thoseShould the brodcast handle authorization or a middleware?
Not sure i understand the question. This broadcast message i was using (and likely the one i will be setting up) will carry over a DTO or just a POPO. It will be on a
private
channel non the less and likely will need to go through policies
Sorry, I’m probably just not seeing the full picture right right now.
Here's the idea. Let's imagine an uptime checker or something. You have a list of sites. Either in a table or Infolist. For each one of thse let's stay you have a
status
item. There is a schedule in the system that periodically fires checks for uptime. When you're looking at the sites list, after the check is done, we update the status
with some information. The idea is to get each one of these sites to subscribe to their own channel and listen to their own events.
So what i'm trying to do now, before i take the custom TextColumn route is figure out a way to access the $livewire instance for a TextColum while in the table() method. Livewire has a setListeners() method that can be called, well, to register listeners.
Yea i think i imagined the setListeners() method. These will have to be custom components 🙂 But no way i'm deaing with this tonight.
Have a good rest of the evening man and thatnk you for your helpFair. For what it’s worth in my mind a poll makes more sense than a broadcast. Instead of keeping a connection open. Just let the browser make a native request for changes and handle it if it’s a dif. But it is relative and something to consider for the use case of the feature.
It’s a good point. The WS integration on my end is still on the exploratory phase. There will be some things that need an open WS channel no matter what, some that are fine with -some level- of polling and some other ones with a hybrid approach : subscription on a page level and rehydrate only when needed