I am working with Filament and Laravel and currently I’ve got these two field inputs for choosing City BASED ON Province Field, inside form()
method:
Select::make("meta.employment_state")
->label("Province")
->getSearchResultsUsing(fn (string $search): array => State::query()->where('name', 'like', "%{$search}%")->limit(10)->pluck('name', 'id')->toArray())
->getOptionLabelUsing(fn ($value): ?string => State::find($value)?->name)
->afterStateUpdated(function (Set $set) {
$set('meta.employment_city', null);
})
->live()
->searchable()
->extraAttributes(['x-data' => '{ selected: false }', 'x-on:change' => 'selected = $event.target.value !== ""'])
->dehydrated(false),
Select::make("meta.employment_city")
->label("City")
->getSearchResultsUsing(fn (string $search, Get $get): array => City::query()->whereRelation('state', 'id', '=', $get('meta.employment_state'))->where('name', 'like', "%{$search}%")->limit(10)->pluck('name', 'id')->toArray())
->getOptionLabelUsing(fn ($value): ?string => City::find($value)?->name)
->placeholder('انتخاب کنید')
->searchable()
->extraAttributes(['x-show' => 'selected', 'x-cloak' => true]),
Basically What I wanna do is that to hide the 2nd input which is city input till the 1st input is getting filled.
This must be done dynamically so I added JS attributes in order to make thing but not working and still shows the City input without the need of filling of province input and this is wrong.
So how to do this with Filament ?
2
Answers
You don’t need to add extra attributes to hide fields. You can use Filament’s
visible()
orhidden()
(docs) methods, combined with $get to get the Form state. Something like this should work:This is hacky, but when it works it works.. ok?
You are on the right path. I’ve done this a few times using alpine and filament’s extraAttributes methods.
You’ll need to treat the elements exactly like you would if you were writing the html/alpine attributes yourself: include x-data on the parent element that wraps elements you want to be dynamic.
The problem with your code is that the alpine elements don’t know about each other. You’ll either need to use
$dispatch
and handle the events from the window on each element, or you’ll need to wrap both elements in another that has your x-data setup.When in doubt, look at the html generated by filament.
Here’s a working example in my filament panel:
NOTE: unless you’re using the
extraAlpineAttributes
method, your values will be html encoded, like the image below. I haven’t found a way to avoid this. As a workaround, I’m dispatching an event from the input element (becauseextraAlpineAttributes
wont encode my quotes) to the element wrapper, which hides updated the wrapper show prop.