Dynamic `required()`/`visible()` within a Repeater

I've got a Form with Select:
return $form
->schema([
Select::make('event_id')
->searchable(['event_locations.name'])
->live()
->relationship(...)
->preload()
->getOptionLabelFromRecordUsing(...),
return $form
->schema([
Select::make('event_id')
->searchable(['event_locations.name'])
->live()
->relationship(...)
->preload()
->getOptionLabelFromRecordUsing(...),
The Event model has certain attributes which inform the requirements of the form, e.g. $event->is_food_provided. Within a Fieldset, updating the visibility of a TextInput works:
Fieldset::make('Participant info')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => Event::find($get('event_id'))?->is_food_provided),
Fieldset::make('Participant info')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => Event::find($get('event_id'))?->is_food_provided),
However, this does not seem to work when it's inside a Repeater:
Repeater::make('participants')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => Event::find($get('event_id'))?->is_food_provided),
]),
Repeater::make('participants')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => Event::find($get('event_id'))?->is_food_provided),
]),
For the Repeater, the visible() check gets executed and is respected on page load, but not when the Select/Event is changed. Is this expected behavior, am I doing something wrong, or is this a bug? I couldn't find anything in the documentation or GitHub issues about this.
7 Replies
toeknee
toeknee2w ago
This is because event_id isn't there. what you want is to traverse out of the repeater.
Repeater::make('participants')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => Event::find($get('../../event_id'))?->is_food_provided),
]),
Repeater::make('participants')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => Event::find($get('../../event_id'))?->is_food_provided),
]),
I think maybe ../ or ../../../ But you just need to to traverse to the right path of where event_id is.
grardb
grardbOP2w ago
@toeknee That worked! Thank you so much. I didn't know about this traversal stuff. Very cool. Follow-up question if you don't mind: There are actually a number of fields that rely on this Event, so I'm calling Event::find($get(...)) multiple times per update. Is there a way to reuse the model that's loaded within the Select to prevent these duplicate queries?
toeknee
toeknee2w ago
@grardb That's a tricky one.. is thise for the fields within the repeater atleast?
grardb
grardbOP2w ago
Some of them - the others are outside the Repeater 😅 It's ultimately not the end of the world (a few extra queries for an admin panel). I just always like to keep DB queries to a minimum.
toeknee
toeknee2w ago
Yeah I hear you, I would write a function on the class, which caches the query if the ID is the same
public function getEvent($event_id)
{
// Create a cache key specific to this event
$cacheKey = "event_{$event_id}";

// Cache for 60 minutes (adjust as needed)
return Cache::remember($cacheKey, 60, function () use ($event_id) {
return Event::find($event_id);
});
}
public function getEvent($event_id)
{
// Create a cache key specific to this event
$cacheKey = "event_{$event_id}";

// Cache for 60 minutes (adjust as needed)
return Cache::remember($cacheKey, 60, function () use ($event_id) {
return Event::find($event_id);
});
}
the you can do:
Repeater::make('participants')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => self::getEvent($get('../../event_id'))?->is_food_provided),
]),
Repeater::make('participants')
->schema([
...
TextInput::make('dietary_requirements')
->visible(fn (Get $get) => self::getEvent($get('../../event_id'))?->is_food_provided),
]),
on save(after function) you could also then do:
Cache::forget("event_{$event_id}");
Cache::forget("event_{$event_id}");
grardb
grardbOP2w ago
Oh, interesting idea! Thanks so much for your help 😁
toeknee
toeknee2w ago
More than welcome!

Did you find this page helpful?