While building a feature in my Laravel + Filament project, I encountered a problem: I needed to automatically associate a newly created Venue with the currently authenticated user ( user_id). This worked fine when creating records directly in the VenueResource, but failed when creating a new Venue inline from a Select field using createOptionForm() in another resource— ConferenceResource.
The Problem
In ConferenceResource, I use a Select::make() field to allow users to choose an existing Venue or create a new one directly from the dropdown. This is done using Filament’s powerful →createOptionForm() method. The catch? When a new Venue is created from this dropdown, the user_id doesn’t get populated. We need a way to inject this extra bit of data into the form submission.
The Step-by-Step Solution
1. Make Your Form Reusable
First, let’s extract the form schema for the Venue into a reusable method on the Venue model.
1 2 3 4 5 6 7 8 9 10 |
// Venue.php public static function getFormOptions(): array { return [ TextInput::make('name')->required(), TextInput::make('location'), // Any other fields... ]; } |
Now update the VenueResource to use this new form definition
1 2 3 4 5 6 7 8 |
// VenueResource.php public static function form(Form $form): Form { return $form->schema( Venue::getFormOptions() ); } |
This keeps your form logic centralized and DRY (Don’t Repeat Yourself).
2. Use It in ConferenceResource
Now let’s use the Venue form inside the ConferenceModel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Conference.php public static function getFormOptions(): array { return [ TextInput::make('name')->required(), Select::make('venue_id') ->label('Venue') ->options(Venue::pluck('name', 'id')->toArray()) ->createOptionForm( Venue::getFormOptions() ) ->createOptionUsing(function (array $data): int { return Venue::create($data)->getKey(); }), ]; } |
Now update the ConferenceResource to use this new form definition
1 2 3 4 5 6 7 8 |
// ConferenceResource.php public static function form(Form $form): Form { return $form->schema( Conference::getFormOptions() ); } |
At this point, the form will open inside the dropdown and allow users to create a new Venue, but it still won’t attach the authenticated user_id. Let’s fix that.
3. Inject Additional Data via mutateFormDataUsing()
This is the missing link. We need to hook into the form submission and mutate the form data before it’s saved:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Conference.php (updated) Select::make('venue_id') ->label('Venue') ->options(Venue::pluck('name', 'id')->toArray()) ->createOptionForm( Venue::getFormOptions() ) ->createOptionUsing(function (array $data): int { return Venue::create($data)->getKey(); }) ->createOptionAction( fn (Action $action) => $action->mutateFormDataUsing(function (array $data): array { $data['user_id'] = auth()->id(); return $data; }) ), |
💡 The →mutateFormDataUsing() method lets you inject or modify form data just before it’s passed to the model’s create() method. In this case, we inject the authenticated user’s ID into the $data array.
Result
With these changes in place, when a user creates a new Venue from within the ConferenceResource form, the user_id is now automatically attached to the Venue record.
📌 Final Thoughts
Filament makes dynamic and reusable forms delightfully easy to build. But when you’re dealing with relational creation like this, don’t forget to use createOptionAction() to fine-tune the data being passed to your models.