Custom Field disappear after LiveWire update

One dev in my team created a PracticeMatrix custom field. Everything was working fine until I added ->live(onBlur: true)->afterStateUpdated(fn (Set $set, ?string $state) => $set('slug', Str::slug($state))), to a TextField to automatically generate a Slug in TextInput::make('slug'). Now, when I blur the TextField, most of the BestPracticeMatrix component disappear and I don't know why. The controller or the blade view are probably not correct, but I'm not familiar with LiveWire and filamentphp custom field. I can't seem to find documentation on how to do custom field. Does anybody knows why the field disappear ? What I know so far is when the blur happen, LireWire update the page and the $practicesData = $getPracticesData(); is now an empty array so the @foreach in the template is not rendering anything. Here is the code: https://gist.github.com/mrleblanc101/f05af5990556f92d8f983c8184dff089
Gist
PracticeMatrix.php
GitHub Gist: instantly share code, notes, and snippets.
Solution:
I guess so, first time using filament and livewire, and this code wasn't from me. But it kinda feels wonky to call PHP methods from the template 😬 Seems like it should be in the Controller and passed down, but that's where it reset the array when LireWire update. But i'm very unfamillar with how to pass data from the Controller to the field, there is basically zero documentation about that. Only how to do a very basic ViewField::make()...
Jump to solution
28 Replies
awcodes
awcodes5mo ago
The table rows need keys
mrleblanc101
mrleblanc101OP5mo ago
wire:key ?
mrleblanc101
mrleblanc101OP5mo ago
I've cleaned it up a little, but adding a wire:key to <x-filament-tables::row> doesn't seem to change anything: https://gist.github.com/mrleblanc101/a88deb517a594ed9adfadc1c3fd59d4e
Gist
gist:a88deb517a594ed9adfadc1c3fd59d4e
GitHub Gist: instantly share code, notes, and snippets.
awcodes
awcodes5mo ago
Then the state of the table is getting reset somewhere in your code.
mrleblanc101
mrleblanc101OP5mo ago
@awcodes Indeed, like I mentioned in my original comment the data is reset when livewire update. Here is a dump of $practicesData at page load, and once livewire update. But I don't know why, the code doesn't interact with LiveWire at all, and it was working before I added ->live() on a entirely different field of the form.
No description
No description
mrleblanc101
mrleblanc101OP5mo ago
We're probably not passing the data from the Controller to the Field correctly, and that's why when LiveWire re-render, the data is now null. But I don't know what's the right way and I can't seem to find docs about this. I'm trying to understand the source code of other filament field, but I'm not knowledgeable enough with livewire and filament to understand yet
awcodes
awcodes5mo ago
Honestly, I’m not totally sure what is happening. Do you have a repo I can look at? Somewhere the state is getting lost
mrleblanc101
mrleblanc101OP5mo ago
Sadly no, it's on a private Gitlab instance. Maybe I can ask someone tomorrow and see. But I doubt the error comes from somewhere else than the 2 code snipped. Odd, if I dump $getStateValues();. I have a value on first render and on livewire update. So the data problem is only with $getPracticesData();
awcodes
awcodes5mo ago
Ok, fair enough, but getPracticesData() is unique to your app, so it hard to give advice on that.
mrleblanc101
mrleblanc101OP5mo ago
You can see the code in the first code snippet, my bad for not including it in the second code snipped (when I did the cleanup in price-matrix.blade.php). I've updated it, you can see the code here: https://gist.github.com/mrleblanc101/a88deb517a594ed9adfadc1c3fd59d4e#file-practicematrix-php
Gist
PracticeMatrix.php
GitHub Gist: instantly share code, notes, and snippets.
awcodes
awcodes5mo ago
Where is $practiceaData coming from? $component->practicesData($practiceData); It’s not being injected into the call back nor is it being accessed from the component.
mrleblanc101
mrleblanc101OP5mo ago
Wdym 🤔 The line just above it $practiceData = self::getPracticeData($record->id);
awcodes
awcodes5mo ago
I’m referring to the setUp method.
mrleblanc101
mrleblanc101OP5mo ago
Yes, this ?
$this->afterStateHydrated(static function ($record, PracticeMatrix $component, $state) {
if ($record) {
$practiceData = self::getPracticeData($record->id);
$component->practicesData($practiceData);
$component->state($practiceData);
}
});
$this->afterStateHydrated(static function ($record, PracticeMatrix $component, $state) {
if ($record) {
$practiceData = self::getPracticeData($record->id);
$component->practicesData($practiceData);
$component->state($practiceData);
}
});
awcodes
awcodes5mo ago
You’re right. Sorry. Wish I had a better answer but it feels like a dom diffing issue to me that I think a wire:key would solve. But you said it didn’t help.
mrleblanc101
mrleblanc101OP5mo ago
I've added wire:key to all element in the @foreach, i didn't know it was needed. I'm a Vue.js guy, so it make sense that it would work the same way
awcodes
awcodes5mo ago
Hopefully someone else has a better answer. But maybe it has something to do with the nested foreach loop. Maybe that’s creating a weird dom diffing issue
mrleblanc101
mrleblanc101OP5mo ago
I've deleted all HTML from my component, only kept the dump and the array is empty when LiveWire update:
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
@php
$id = $getId();
$statePath = $getStatePath();
$practicesData = $getPracticesData();
$stateValues = $getStateValues();
$rowKey = 1;

$groupedPractice = collect($practicesData)->sortBy(['category_practice_name', 'name'])->groupBy('category_practice_name');
dump($practicesData)

@endphp
</x-dynamic-component>
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
@php
$id = $getId();
$statePath = $getStatePath();
$practicesData = $getPracticesData();
$stateValues = $getStateValues();
$rowKey = 1;

$groupedPractice = collect($practicesData)->sortBy(['category_practice_name', 'name'])->groupBy('category_practice_name');
dump($practicesData)

@endphp
</x-dynamic-component>
I have no idea how to debug this, seems like if it was a DOM difing issue, it would be logged to the console, no ?
awcodes
awcodes5mo ago
Not necessarily
mrleblanc101
mrleblanc101OP5mo ago
No description
awcodes
awcodes5mo ago
Yea. Not sure. Sorry. Somewhere the state is getting lost in the request.
mrleblanc101
mrleblanc101OP5mo ago
I'm not even sure I understand what is called when LiveWire update, the whole setUp, just afterStateHydrated, something else ? I litteraly remove everything from setUp and only left static hardcoded data, and the value are also lost 😭
protected function setUp(): void
{
parent::setUp();

$this->afterStateHydrated(static function ($record, PracticeMatrix $component, $state) {
if ($record) {
$component->practicesData(['data' => 'test']);
}
});
}
protected function setUp(): void
{
parent::setUp();

$this->afterStateHydrated(static function ($record, PracticeMatrix $component, $state) {
if ($record) {
$component->practicesData(['data' => 'test']);
}
});
}
Could this be a bug in Filament or LiveWire and not in our code 😮
mrleblanc101
mrleblanc101OP5mo ago
No description
mrleblanc101
mrleblanc101OP5mo ago
Just noticed filament is a couple version outdated 3.2.73 instead of the current 3.2.97. Will try that Nope, not it 😦 @awcodes I think I found a solution, I do know if it's correct or clean tho. So instead of calling $getPracticesData() (with an "s") in the template. I call $getPracticeData() without an "s" in the template, the issue I had is that it require an id params (public static function getPracticeData($id)) which was received from afterStateHydrated in the setUp. But from the doc I saw I could get the record in the template using $getRecord() which mean I can use $practicesData = $getPracticeData($getRecord()->id);
awcodes
awcodes5mo ago
If it works it isn’t wrong. It may or may not possibly be more clean or optimized, but if it works it’s not wrong.
Solution
mrleblanc101
mrleblanc1015mo ago
I guess so, first time using filament and livewire, and this code wasn't from me. But it kinda feels wonky to call PHP methods from the template 😬 Seems like it should be in the Controller and passed down, but that's where it reset the array when LireWire update. But i'm very unfamillar with how to pass data from the Controller to the field, there is basically zero documentation about that. Only how to do a very basic ViewField::make()
awcodes
awcodes5mo ago
Sometimes you have to break convention to accomplish the goal. Doesn’t make it right or wrong.
mrleblanc101
mrleblanc101OP5mo ago
Well nvm, nothing save anymore lol But hey, at least the field doesn't disappear 🤷‍♂️ Ok, but that might be related to my earlier refactor to change <input> and <select> to <x-filament::input> and <x-filament::input.select> Ah no, it's ok. Just a bug from when I reverted the composer.lock and public/ assets so that I didn't push unecessary changes. I re-ram composer install and php artisan filament:upgrade to properly revert to the previous version. I'll upgrade everything in another branch / merge-request later Thanks a lot for your help @awcodes 🚀
Want results from more Discord servers?
Add your server