F
Filamentโ€ข3mo ago
PabloZagni

How to refresh a relationManager after Action on Owner.

Hi. I have an ISSUE tracking system. In the viewform of the Issue, I have an action to change ISSUE priority. It opens a modal with a select for the new priority. Then, the action updates the ISSUE and adds a record to the "activities" registering that change. The view has a relationshipManager with all the activities of the ISSUE, I can refresh the "priority_id" field of the view (since it was modified) but How can I refresh the relationshipManager to show the new record?
No description
No description
10 Replies
Dennis Koch
Dennis Kochโ€ข3mo ago
Since RMs are Livewire components you should be able to dispatch a Livewire Event and Listen on the RM component to refresh it
slakkie
slakkieโ€ข3mo ago
Hey @Dennis Koch trying to figure out what the correct way to dispatch a Livewire Event and Listener. Can't seem to find specifics in the docs. Do you maybe have some pointers, I've tried and search a lot: I have a ProductResource and next to each product in a filament table I have a add to cart button/action:
->actions([
Action::make('basket')
->requiresConfirmation()
->after(function () {
$this->dispatch('updated_cart'); <-- throws error: Using $this when not in object context
})
->action(function (Event $record) {
app()->make('cart')->addEvent($record->id);
}),
])
->actions([
Action::make('basket')
->requiresConfirmation()
->after(function () {
$this->dispatch('updated_cart'); <-- throws error: Using $this when not in object context
})
->action(function (Event $record) {
app()->make('cart')->addEvent($record->id);
}),
])
First when I try to dispatch the event like in the above code I get an error: Using $this when not in object context Also tried the one below does not throw an error but I am also not sure if the event is even dispatched at all:
->after(function (StaticAction $action) {
$action->dispatch('updated_cart');
})
->after(function (StaticAction $action) {
$action->dispatch('updated_cart');
})
There's a simple filament page with a side navigation and a badge counter. I've tried various ways to listen for the event without getting it to refresh. When a user add an item to the cart the counter should update via listening for the 'updated_cart' event:
class Cart extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-shopping-cart';

protected static string $view = 'filament.pages.test';

protected $listeners = ['updated_cart' => '$refresh']; <-- tried this

#[On('updated_cart')] <-- tried this
public static function refreshBadgeCount()
{
$count = app()->make('cart')->eventCount();

return $count > 0 ? $count : null;
}

#[On('updated_cart')] <-- tried this
public static function getNavigationBadge(): ?string
{
return static::refreshBadgeCount();
}
class Cart extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-shopping-cart';

protected static string $view = 'filament.pages.test';

protected $listeners = ['updated_cart' => '$refresh']; <-- tried this

#[On('updated_cart')] <-- tried this
public static function refreshBadgeCount()
{
$count = app()->make('cart')->eventCount();

return $count > 0 ? $count : null;
}

#[On('updated_cart')] <-- tried this
public static function getNavigationBadge(): ?string
{
return static::refreshBadgeCount();
}
I suspect dispatching is the problem.
Dennis Koch
Dennis Kochโ€ข3mo ago
For dispatching you might need to dispatch on the compontent
->after(function (StaticAction $action, $livewire) {
$livewire->dispatch('updated_cart');
})
->after(function (StaticAction $action, $livewire) {
$livewire->dispatch('updated_cart');
})
And I guess you can't refresh just the badge so you need to listen on the component:
#[On('updated_cart')]
class Cart extends Page {}
#[On('updated_cart')]
class Cart extends Page {}
slakkie
slakkieโ€ข3mo ago
Thanks for the feedback! Appreciate it a lot, been struggling with this for many hours. I've also tried what you proposed, that but the listener is not reached. Maybe I should just restate that the ProductResource is a standard Filament resource component with a table and the add to cart button next to each row. When the user click the button the item is added via a service to a cart. The Cart component is also separate component (Page component) not related to the ProductResource at all, with just a page and a navigation item with a badge with the count of items in the cart. So what I want to achieve is that when a product is added to the cart that the left navigation counter badge updates. I thought the easiest would be to dispatch an event and have the Cart component refresh. But as mentioned the listener is not reached. I was wondering if the standard navigation item itself is refreshable, or if the navigation pane can be refresh upon an event or event hook?
No description
No description
Dennis Koch
Dennis Kochโ€ข3mo ago
Ah. Since you are in a separate component the listener on the Cart component won't work. because it's not mounted. You could try a listener on the ListProducts page to refresh the current site. Not sure what's the ideal solution here
slakkie
slakkieโ€ข3mo ago
Yeah I saw some people are redirecting after the action completed... it feels strange ๐Ÿ™‚
Dennis Koch
Dennis Kochโ€ข3mo ago
I haven't tried this, but maybe you could return an HTML element with Alpine listener for the badge. Something like this:
return new HtmlString('
<span
x-data="{ count: 0 }"
x-on:update-cart.window="count = $event.count"
x-text"count"
></span>
');
return new HtmlString('
<span
x-data="{ count: 0 }"
x-on:update-cart.window="count = $event.count"
x-text"count"
></span>
');
And then dispatch an event to the frontend:
$this->dispatch('update-cart', ['count' => $newCount]);
$this->dispatch('update-cart', ['count' => $newCount]);
slakkie
slakkieโ€ข3mo ago
interesting ok going to give that a shot on the method in the Page which gets the count:
public static function getNavigationBadge(): ?string
{
return static::refreshBadgeCount();
}
public static function getNavigationBadge(): ?string
{
return static::refreshBadgeCount();
}
Just for interest sake on: https://filamentphp.com/docs/3.x/notifications/sending-notifications#dispatching-livewire-events-from-notification-actions There is a method on the notifications component, which can do:
->dispatchTo('another_component', 'undoEditingPost', [$post->id])
->dispatchTo('another_component', 'undoEditingPost', [$post->id])
So when I bring in the $action that method also exists on it for example:
->action(function (Event $record, StaticAction $action, $livewire) {

$action->dispatchTo('app.filament.resources.pages.cart', 'updated_cart');
->action(function (Event $record, StaticAction $action, $livewire) {

$action->dispatchTo('app.filament.resources.pages.cart', 'updated_cart');
But not sure yet how that works and what the name is of the component I just pulled that name with the getName() method of the Cart component. Anyway will quickly try that Alpine way
slakkie
slakkieโ€ข3mo ago
Hey @Dennis Koch thanks again for all the help. Seems like the badge just takes in a string it is not Htmlable, which would mean I need to override: resource\views\component\sidenav\item.blade.php ... and that is of course not optimal. I think for now I am going to settle on this non-optimal way:
->action(function (Event $record, StaticAction $action, $livewire) {
app()->make('cart')->addEvent($record->id);
$action->redirect(request()->header('Referer'));
->action(function (Event $record, StaticAction $action, $livewire) {
app()->make('cart')->addEvent($record->id);
$action->redirect(request()->header('Referer'));
Again thanks for the help!! Hopefully it's something that will be easier in the future.
slakkie
slakkieโ€ข2mo ago
GitHub
refresh navigation badge ยท filamentphp filament ยท Discussion #7221
Table polling works fine, but how can I update the corresponding navigation badge so that they are in sync?
Want results from more Discord servers?
Add your server