F
Filament10mo ago
Wirkhof

$wire.$refresh() doesn't work

I want to do something like this:
@click="$wire.doSomethingHere(), $wire.$refresh()"
@click="$wire.doSomethingHere(), $wire.$refresh()"
The first doSomethingHere() will run ok, but $wire.$refresh() don't . How to make $wire.$refresh() work?
Solution:
yep, your LW component is updating.. Could you try another test? ```php <div wire:key="{{ $p->id . now() }}"> ......
Jump to solution
66 Replies
Wirkhof
WirkhofOP10mo ago
Is there any other javascript way of making the component I am in refresh? I did some DB changes and I don't see them. To see them I need to manually refresh the page. But it should be possible via Livewire to rerendering the component, right? The only way I know how to make it work is this:
@click="$wire.doSomethingHere(), location.reload()"
@click="$wire.doSomethingHere(), location.reload()"
This will refresh the page. But it's not nice and it's disruptive and not SPA like at all. Do you know about a clever javascript way how to make livewire/alpine refreshthe current page/component so it looks like a SPA refresh and not a hard manual browser refresh?
awcodes
awcodes10mo ago
Just dispatch refresh in your doSomething() method. No need to do it from the click.
Wirkhof
WirkhofOP10mo ago
$this->dispatch('refresh'); is doing nothing. I don't see any error but it does nothing. I have also tried $this->dispatch('$refresh') but it's the same. Nothing happens. I have a custom component.
awcodes
awcodes10mo ago
Try $this->refresh()
Wirkhof
WirkhofOP10mo ago
I am getting:
BadMethodCallException
BadMethodCallException
to be precise:
Method App\Filament\Resources\CarResource\Pages\EditCar::refresh does not exist.
Method App\Filament\Resources\CarResource\Pages\EditCar::refresh does not exist.
the doSomethingHere() method is at the end the Edit record php page to the resource, that file that is used for the edit form related stuff normally. Like I said it is being called and the DB stuff and logic will run when I call it from @click But if I add $this-refresh() as the last thing after the DB and logic stuff I get this BadMethodCallException.
Wirkhof
WirkhofOP10mo ago
No description
Wirkhof
WirkhofOP10mo ago
Above is the error I am getting via Flare. As you can see, there is other commented stuff I have tried already that isn't working either. What could be wrong? Do I have to import some class to make $this->refresh() working in that file for Edit form? I can dd($this) or dd($this->data) and I see the corresponding stuff there, so $this is clearly available. Not sure why refresh() is missing in $this though? There really should be some clever way how to do the refresh. How it the wire:poll doing that stuff?
Wirkhof
WirkhofOP10mo ago
There is some issue I have no knowledge how to fix. I am using a workaround for now:
<div x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
async selectRedCars() {
await this.$wire.selectRedCars()

location.reload()
}
}" x-init={}>
<button @click="await selectRedCars()">...</button>
</div>
<div x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
async selectRedCars() {
await this.$wire.selectRedCars()

location.reload()
}
}" x-init={}>
<button @click="await selectRedCars()">...</button>
</div>
The devil will be in the entangle and state part I have no idea how it works. One has to make it to refresh the page or component in the code, but it's beyond my current understanding of Filament.
ryangjchandler
ryangjchandler10mo ago
I think there's a gap in your Livewire knowledge here. Calling a method inside of a Livewire component implicitly re-renders the component, since you're making a trip to the server and Livewire is re-rendering your component and then updating the DOM from the response. Calling $this->refresh() on the server doesn't do anything, because you're already in the process of re-rendering things anyway. The only case where a re-render is skipped on the server is if you're explicitly calling $this->skipRender() inside of the Livewire component.
Wirkhof
WirkhofOP10mo ago
What solution do you suggest? How to re-render my custom form component? Currently it is not rerendering no matter what, unless I do manual browser refresh via that async function above.
ryangjchandler
ryangjchandler10mo ago
Have you got a screen recording or something to show that it's not re-rendering?
Wirkhof
WirkhofOP10mo ago
Sorry, but I have my own eyes. I see when the records that are being changed are stalled or not. If I do hard refresh of the page - they change. The code in the blade template did run again. The DB query result reflects what changed. Again, it's a custom component. I have there a custom DB queries that are clearly not rerun normally - otherwise the result will be different. I am not even using any Filament fields. It's basically an iframe without an iframe. All I am using is the db and custom PHP logic to output the result on the page and Alpine to interact with it. I don't even need any Filament abstractoin or whatever. At this point I truly think it's mostly counterproductive. The thing I want to redo in Filament I did in few hours in my old Laravel project. Now I can't make it work properly with Filament because how it does rendering. In pure Livewire I have something similar on the frontend and it's super easy to do, but in Filament it's a road-block after road block. I won't be using it for any further projects for sure. too much opinionated stuff that gets in your way as long as you want to do something custom. Filament is cool for basic stuff but anything custom is a pain in the ass. It's just buffling one can't use a custom php code in the middle of a form and make it refresh on pressing the save button or whatnot. There is not a simple solution to do that. That's a fundamental problem with Filament. OK, make it non-default. But at least make it POSSIBLE. With some flag or option or whatever.
ryangjchandler
ryangjchandler10mo ago
There's no need to be rude. We're trying to help understand your problem more.
Wirkhof
WirkhofOP10mo ago
But it's such a basic thing.
ryangjchandler
ryangjchandler10mo ago
Are you doing any loops inside of the Blade template? Filament doesn't do anything special when it comes to rendering. It's all Livewire still.
Wirkhof
WirkhofOP10mo ago
Tell me one thing.
ryangjchandler
ryangjchandler10mo ago
If you can see the data updating on the server-side, then it'll likely be one of the following things: * Missing wire:key attributes on elements inside of a loop. * A wire:ignore attribute on a parent element, which prevents the DOM being updated.
Wirkhof
WirkhofOP10mo ago
Why isn't the feature to be able to reload a component or a whole page in built? I have asked it before and everybody was hasitant.
ryangjchandler
ryangjchandler10mo ago
If you give us more information, we'll be able to help you out. You're just being difficult now. Are you using loops inside of your Blade? Are you using wire:ignore anywhere?
Wirkhof
WirkhofOP10mo ago
Again, it's a custom component i am not using no wire;ignore
ryangjchandler
ryangjchandler10mo ago
Any loops?
Wirkhof
WirkhofOP10mo ago
And again one question HOW DO YOU REFRESH A COMPONENT? a custom component to be precise. I am not using any loops
ryangjchandler
ryangjchandler10mo ago
In order to get help, you have to be willing to share more information. "Custom component" doesn't help.
Wirkhof
WirkhofOP10mo ago
I can send you a link
ryangjchandler
ryangjchandler10mo ago
Sure, send me a link.
Wirkhof
WirkhofOP10mo ago
Damn, the website is so hard to navigate
ryangjchandler
ryangjchandler10mo ago
Okay, I'll come back to help once you provide us with more information.
Dan Harrin
Dan Harrin10mo ago
@Wirkhof you need to calm down or I'm just going to ban you dude, we don't need this in our lives final warning look around you at every other user in the server and how they behave, and compare yourself. be grateful you have somewhere that people might be willing to help you, it might not be here for you for long.
Wirkhof
WirkhofOP10mo ago
There is not more I can find. If you put there a DB::table('cars')->get(); let's say here:
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
@php
$record = DB::table('cars')->first();

print_r($record);

@endphp

// alpine code to call a method in EditCar.php that will change the DB records here
// but the method will run and at the end the rerender of this x-dynamic
// component won't happen
// despit th record in the DB will.
</x-dynamic-component>
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
@php
$record = DB::table('cars')->first();

print_r($record);

@endphp

// alpine code to call a method in EditCar.php that will change the DB records here
// but the method will run and at the end the rerender of this x-dynamic
// component won't happen
// despit th record in the DB will.
</x-dynamic-component>
This is a simplified version describing the issue. I would expect the method in the EditCar.php I am callling to trigger rerendering of the page or component. But that is not happening. I am guessing you have to register what will be rerendered somewhere. But this information is nowhere to be found. Any idea where can this be setup? The first two lines are basically identical as in the Filament docs:
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div x-init={} x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div x-init={} x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
I've only added x-init={} and x-data to it. Could that mess things up? I have tried to put a dive around the foreach loop I have tried to put wire:key with id of that row around each element inside foreach loop nothing works. It's not rerendering at all. It's completely stale for some reason. The only thing that works and I can see the changes done by the method selectRedCars(), albeit it's a drastic rerender and not a smooth spa like experience, is this:
<div x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
async selectRedCars() {
await this.$wire.selectRedCars()

location.reload()
}
}" x-init={}>
<button @click="await selectRedCars()">...</button>
</div>
<div x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
async selectRedCars() {
await this.$wire.selectRedCars()

location.reload()
}
}" x-init={}>
<button @click="await selectRedCars()">...</button>
</div>
Although it has to be done in this async mode. If done like this:
<div>
<button @click="$wire.selectRedCars(), location.reload()">...</button>
</div>
<div>
<button @click="$wire.selectRedCars(), location.reload()">...</button>
</div>
It won't work correctly. It will mess up the DB part in the EditCar.php method selectRedCars() for some reason. If any of you guys know how to make it work without location.reload() let me know. Thanks in advance.
wyChoong
wyChoong10mo ago
Share your component in gist
Wirkhof
WirkhofOP10mo ago
OK, will post link
LeandroFerreira
LeandroFerreira10mo ago
in the selectRedCars method, do:
$this->getRecord()->refresh();
$this->fillForm();
$this->getRecord()->refresh();
$this->fillForm();
Wirkhof
WirkhofOP10mo ago
Here is the code https://pastebin.com/6ebtC0C4 and the second file https://pastebin.com/R4JG1icc Ideally, just the wire:click="selectRedCars" would go to the method in EditCar.php, do the DB update code and at the end did the refresh. Currently the pastebined code is not working. To make it work I need to use the alpine JS code with async I posted a few posts above. And one more thing that might be important. I do this to add it in the form in the resource file:
wyChoong
wyChoong10mo ago
what is your code in selectRedCars
Wirkhof
WirkhofOP10mo ago
return $form
->schema([
Section::make('Options')
->hiddenOn('create')
->schema([
Tabs::make('Tabs - Colors')
->tabs([
Tabs\Tab::make('Red')
->schema([
RedCars::make('')
->label(''),
]),
return $form
->schema([
Section::make('Options')
->hiddenOn('create')
->schema([
Tabs::make('Tabs - Colors')
->tabs([
Tabs\Tab::make('Red')
->schema([
RedCars::make('')
->label(''),
]),
I deleted the string from make() because it wanted to query the DB for something but I didn't want it to be asociated with any db table or model etc. so I think it was originally RedCars::make('redcars') or something but it was throwing DB error that I don't have such table or something so I changed it to RedCars::make('') and Filament was cool after that. It's one DB update. And I have tried everything at the end what you have suggested. Currently it ends like this:
LeandroFerreira
LeandroFerreira10mo ago
What about your selectRedCars method?
Wirkhof
WirkhofOP10mo ago
Thanks, the Column not found error will not show with ->dehydrate(false) and I can use a name in make() again. Thanks for that. But it's still not refreshing
LeandroFerreira
LeandroFerreira10mo ago
Is EditCar.php a custom livewire component or a page in the CarResource?
Wirkhof
WirkhofOP10mo ago
😭 a page one of those three default pages. create, edit, list
LeandroFerreira
LeandroFerreira10mo ago
Did you try this code in the selectRedCars method?
$this->getRecord()->refresh();
$this->fillForm();
$this->getRecord()->refresh();
$this->fillForm();
Wirkhof
WirkhofOP10mo ago
public function selectRedCars()
{

Car::where('is_published', true)->update([
'selected' => true
]);

$this->getRecord()->refresh();
$this->fillForm();

}
public function selectRedCars()
{

Car::where('is_published', true)->update([
'selected' => true
]);

$this->getRecord()->refresh();
$this->fillForm();

}
This is the method in the EditCar.php The query itself works that's not an issue. I have only the queary and nothing else there. No other logic. I have done it without any passed variables, just like here. And it still doesn't work. By doesn't work. I mean the refresh part. Query runs perfectly I see it when I refresh TablePlus. The changes are there. But to see them on the screen I have to manually refresh the browser. or use the "hack" with location.reload() and the async code.
LeandroFerreira
LeandroFerreira10mo ago
any console errors?
Wirkhof
WirkhofOP10mo ago
No errors in console. I see it loads the update livewire file/endpoint no 500 errors in console I see the notification toast appear when I click on the button, that's weird
LeandroFerreira
LeandroFerreira10mo ago
add type="button" in the button
Wirkhof
WirkhofOP10mo ago
When I add type="button" the notification stops showing. when I remove it it will show again. Is this normal? The query was reached in both cases. I see it when I do the browser manual refresh and in TablePlus. only the automatic refresh part is not working.
LeandroFerreira
LeandroFerreira10mo ago
Yes, the button will prevent the form from being submitted.
Wirkhof
WirkhofOP10mo ago
OK, I think this is unsolvable. Thanks anyway.
LeandroFerreira
LeandroFerreira10mo ago
This was supposed to work.. lets do another test: Add this in the EditCar.php please
use Livewire\Attributes\On;

#[On('forceRefresh')]
public function forceRefresh()
{
}

public function selectRedCars()
{
//your update...

$this->dispatch('forceRefresh');
}
use Livewire\Attributes\On;

#[On('forceRefresh')]
public function forceRefresh()
{
}

public function selectRedCars()
{
//your update...

$this->dispatch('forceRefresh');
}
Wirkhof
WirkhofOP10mo ago
Nothing 😭 still no refresh the query runs normally though
LeandroFerreira
LeandroFerreira10mo ago
weird if you add dd('xxx') in the forceRefresh method?
Wirkhof
WirkhofOP10mo ago
I see the black window with xxx as with normal dubugging. that works. so forceRefresh function is run, right?
LeandroFerreira
LeandroFerreira10mo ago
yes, it shouldn't be necessary, just to test this. Are you able to share this project with me on Github?
Wirkhof
WirkhofOP10mo ago
Unfortunatelly not. But thanks a lot for your time. It will be something unusual. Is there any article or video on making a custom form field or plugin for Filament 3?
LeandroFerreira
LeandroFerreira10mo ago
if you add {{ now() }} in the view, is the date updated?
LeandroFerreira
LeandroFerreira10mo ago
Laracasts
Build Advanced Components for Filament
Once you're confidently building interfaces with all the components that are included with Filament, you'll likely want to begin building your own custom ones. Hi, I'm Dan: the co-founder of Filament. This series will teach you how to build components, like custom form fields and table columns, and how to distribute them in a plugin package. Me...
Wirkhof
WirkhofOP10mo ago
thanks that's weird {{ now() }} will be refreshed even with just wire:click
LeandroFerreira
LeandroFerreira10mo ago
you can also remove the force refreshed method that it will work
Wirkhof
WirkhofOP10mo ago
will try YES! even without the On: attribute and forceRefresh it's updating. now I have to find out why the other part is not working Perhaps I will send it again from the method
Solution
LeandroFerreira
LeandroFerreira10mo ago
yep, your LW component is updating.. Could you try another test?
<div wire:key="{{ $p->id . now() }}">
...
<div wire:key="{{ $p->id . now() }}">
...
Wirkhof
WirkhofOP10mo ago
OK, will try the id with time It's changed as well, for all records in @foreach loop Now it started working! could the time helped/ ? I had only id there so far WOW! perhaps the id itself was not enough for some reason? Before it looked like this wire:key="936" and now with time wire:key="9362024-03-21 17:34:39" Could LW thought that it's not changed and now with time it's different for him so he is swapping it?
LeandroFerreira
LeandroFerreira10mo ago
It was supposed to work. Add now() is a trick when I want to make a child Livewire component "reactive"...
Wirkhof
WirkhofOP10mo ago
Thanks man. It was quite a journey.
Wirkhof
WirkhofOP10mo ago
It perhaps has some connection to this another issue with Tailwind, but that's not very important: https://discord.com/channels/883083792112300104/1220278968599707738 But it could be something else. But styling a custom component for this particular specific case is a non-issue. I can easily do that in theme.css etc. Again, thank you Leandro.

Did you find this page helpful?