Enum cast not working when editing a resource
I have a model "Article" with a "category" field. This Field is being cast to an enum ArticleCategory::class. The Enum class is implementing Filament\Support\Contracts\HasLabel.
In my ArticleResource form I am populating a select input using ->options(ArticleCategory::class). I am also providing ->default(ArticleCategory::STORY) to set the default during article creation. Further down in my form I have a conditional grid, which only gets displayed, if $get('category') matches ArticleCategory::REVIEW
Everything works when creating a new article. During editing however, I noticed that my conditional grid is never displayed. Upon further inspection I found out that the value for "category" was not an instance of my Enum class, but just a plain String.
I was able to fix my issue using this piece of Code in my EditArticle.php file:
This feels rather cumbersome, as I was expecting that Filament would take my Enum Cast into account during editing, considering that the Select Input works so nicely with Enum classes.
Is this a bug? Or is there a simpler way to do this? Or is this already the proper way to do this?
24 Replies
can you post the code for your Form?
I'm wondering how you're presenting the conditional, in the context of the rest of how the form is constructed.
Pretty much what is listed here: https://filamentphp.com/docs/3.x/forms/advanced#dynamic-fields-based-on-a-select-option just with my Enum class instead of Strings
okay. I'm trying to narrow things down to where the code could check for
is_a(enum)
and have it call ->value
on it. Just gotta figure out what's needing the code added into to support it. ... cuz if it's a reasonable expectation to need to support it, then a PR is probably easily welcomed.Casts only work when data goes into and out of the database. So when referencing $data the cast is not relevant so anything you do with data would default to how enums are used natively in php.
So, in $data it won’t be an enum it will be a string.
There might be something else going on. As I continue working on my Form I now get a Livewire crash with "Object of class App\Enums\ArticleCategory could not be converted to string" when submitting my form
An additional livewire error get's thrown when I change the value of my select input: Uncaught (in promise) TypeError: Cannot convert undefined or null to object
at Function.values (<anonymous>)
at file-upload.js?v=3.1.11.0:40:84644
at livewire.js?id=f477dd12:844:11
Not 100% sure where the issue originates as I basically copypasted the code from the doc section mentioned above
Is all this related to your "conditional" segment? Does the problem follow if you remove that conditional segment?
yeah, seems to be related to that
If you add things back bit by bit, which part "breaks" it?
can't really narrow it down further. For a moment I thought it could be an issue that my conditional grid includes other sections in its schema, but the bug only disappears if i remove the full conditional grid
Mind posting your code for the class? I know you said it's almost straight from the docs, but you mentioned adding the mutate, and cuztomizing the grid, etc.
Yea, code would help us. Mutate happens at a different lifecycle point than rendering does.
Sure thing! This is my current state: https://gist.github.com/lpeterke/e3134741929627dfdda84b821b15a626
Does this error disappear if you remove the file-upload component? I don't see any reason for that to be a problem in your code. Unless it's related to something the SpatieFileUpload component is drawing from your Model.
I suppose you could try switching it to a regular FileUpload component as an alternate test (but I understand how that's not desirable when you've got the other already integrated). If the error persists (ie: falls through to another element) that'll reveal more. Looks like you removed the
I suppose you could try switching it to a regular FileUpload component as an alternate test (but I understand how that's not desirable when you've got the other already integrated). If the error persists (ie: falls through to another element) that'll reveal more. Looks like you removed the
mutateFormDataBeforeFill()
call?For starters this is going to break anything and everything
->afterStateUpdated(fn (Forms\Components\Select $component) => $component
But it came from https://filamentphp.com/docs/3.x/forms/advanced#dynamic-fields-based-on-a-select-option (although the indentation is lost in the gist)
Sorry, formatting issue. I’m on my phone.
Yeah figured that also out just now 😄 its 3AM, I'll probably need to continue tomorrow with a fresh pair of eyes. But thank you guys so much already for helping me figuring this out!
It could be the fact that you are using dot syntax on the grid’s sub fields. If that is not a relationship you should probably define a statePath on the grid and not use dot syntax for the field’s make() names.
I don’t think dot syntax works on form fields the way it does on tables.
Ill check it tomorrow. But the form fills perfectly when opening an existing article from my DB so i just assumed its all Fine Like this 🤔
@awcodes @DrByte Okay, so i figured out a few things:
1. The code for afterStateUpdated() at https://filamentphp.com/docs/3.x/forms/advanced#dynamic-fields-based-on-a-select-option did not work for me, because my conditional grid had other layout components nested in it's schema. This caused the fill() method to mess up my form. I had to adjust the code like this to get it working:
2. Fixing the first part introduced another issue. When editing an existing "review" article, all field in my conditional grid would loose their values forever, if I would switch the article category from "review' to something else and then back to "review". I was able to fix this by injecting the Livewire component instance and passing it's data to the fill() method.
3. There seems to be a bug with the DatePicker and DateTimePicker when using their JavaScript implementation with ->native(false). As soon as I change my article category using the select modal my console is getting flodded with stuff like "Alpine Expression Error: focusedMonth is not define" followed by errors like this:
Aaaand I think that's beyond my knowledge. If I use the native DatePicker the error goes away.
That being said, my form now seems to work perfectly, both for creating and editing. My issue however persists: when submitting my form (both on edit or create) I get "Object of class App\Enums\ArticleCategory could not be converted to string". But I was able to narrow this down a bit:
- The issue only occurs when my article category is set to 'review'
- The issue disappears when i remove my conditional grid.
Hope this info helps!
Can you share the actual Enum class?
Wait, I think I just found the error.
So I removed the cast from my model and... the issue persisted. Which was really weird. Then I saw that at the end of my form, in my conditional grid. I had two fields with this piece of code: ->requiredIf('category', ArticleCategory::REVIEW)
That was the issue. Changing it to ->requiredIf('category', ArticleCategory::REVIEW->value) fixed the bug. However, as both fiels are inside the conditional grid, I didn't even need the check and could just use ->required()
Glad you got it sorted!