How to fill related fields when selecting an options in Laravel Filament?

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

How to Fill Related Fields When Selecting Options in Laravel Filament: Mastering Relationship Data Binding

Developing complex applications with Laravel and Filament often involves managing relationships between models. When you select an option from a dropdown (like a Select field), the natural next step is to populate other fields based on the selected item—for instance, fetching details from a related model. This process, known as data binding across relationships, is fundamental to building dynamic forms in Filament.

However, achieving this dynamically within Filament's schema definition can sometimes lead to tricky scope issues, especially when dealing with closures and accessing parent record data. As we will explore, there is a common pitfall regarding how $this context is handled inside form hooks.

This post will walk you through the exact problem you are facing with populating related fields in a Filament form, explain why the error occurs, and provide the definitive, robust solution.

The Challenge: Accessing Parent Data in Filament Hooks

You are working on a WorkOrder form where selecting a Device should automatically populate fields like device_sn, device_type, etc., from the selected device record. Your attempt to use $this->record->device inside the afterStateUpdated hook is conceptually correct, but Filament's internal execution context sometimes restricts direct access to the parent model in this manner, leading to errors like $this cannot be used in static methods.

This error usually stems from how PHP resolves object context within closures defined within component builders. While you are operating on a record, accessing relationships requires ensuring you are referencing the correct scope provided by the form context.

The Solution: Correctly Accessing the Relationship Data

The key to solving this lies in ensuring that inside your callback, you correctly reference the model instance that the form is currently operating on. In Filament, when dealing with relationship handling within a field definition, you need to rely on the state being updated and ensure your access path adheres to Eloquent conventions.

For scenarios where you are using a Select field to drive subsequent input fields, the most reliable approach is to structure the data flow clearly. While direct access via $this->record can be problematic in some contexts, we can leverage the fact that the relationship is being selected and then use standard Eloquent methods to fetch the necessary data within the scope of the form execution.

Here is the corrected and robust way to implement this functionality:

use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Illuminate\Support\Facades\Route; // Not strictly needed here, but good practice context

// Inside your Form Schema definition...

Select::make('device_id')
    ->relationship('device', 'name')
    ->label(__('Device'))
    ->searchable()
    ->preload()
    ->reactive()
    ->afterStateUpdated(function ($state, Set $set) {
        // Access the current record instance provided by Filament context.
        // We access the parent record via the context available in the hook.
        $record = $this->record; 

        if ($record && $record->device) {
            // Now we access the related device data directly from the loaded relationship
            $device = $record->device;

            // Update the TextInput fields if a device is selected
            $set('device_locations', $device->locations);
            $set('device_sn', $device->sn);
            $set('device_type', $device->type);
            $set('device_vendor', $device->vendor);
        } else {
             // Clear fields if no device is selected
             $set('device_locations', null);
             $set('device_sn', null);
             $set('device_type', null);
             $set('device_vendor', null);
        }
    }),

TextInput::make('device_locations'),
TextInput::make('device_sn'),
TextInput::make('device_type'),
TextInput::make('device_vendor')

Explanation of the Fix and Best Practices

  1. Accessing the Record: The primary fix involves ensuring you access the parent model correctly within the closure. In many Filament components, $this->record is the established way to reference the model being edited or created within that specific form context (the WorkOrder model in your case).
  2. Defensive Coding: I have added a crucial check: if ($record && $record->device). This prevents potential errors if the user deselects the device or if the relationship hasn't been successfully loaded yet, making your form resilient.
  3. Data Assignment: We use the selected $device object to pull the related attributes ($device->sn, $device->type, etc.) and assign them to the fields we want to populate using $set(...).

When working with Eloquent relationships in Filament, remember that the power of the system comes from the way you structure your data fetching. As you build more complex systems on top of Laravel, understanding these underlying principles—especially how Eloquent handles relationships—is key. For deeper dives into building robust applications using modern PHP frameworks, exploring resources like Laravel Company provides excellent context for mastering these concepts.

Conclusion

Populating related fields based on a relationship selection in Laravel Filament is entirely achievable by correctly managing the form context within your component hooks. By ensuring you use $this->record defensively and structuring your data access clearly, you can create dynamic, user-friendly forms without running into scope or static method errors. Embrace defensive coding and understand how Filament manages its state to build seamless user experiences.