Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

El Klo's avatar
Level 11

Set Filament Checkboxlist dynamically

I have the following checkboxlist in a filament form:

CheckboxList::make('contact_ids')
						->reactive()
			            ->options([])
			            ->columns(1),

I want to update the shown checkboxes based on this relationship:

public function contacts(): HasManyThrough {
		return $this->hasManyThrough(Contact::class, Client::class);
	}

When a user selects a certain client in the Select::make('client_id), i want the checkboxlist to be updated to show the results of the contacts relationship. So far, i have the following selection:

Select::make('client_id')
					      ->relationship('client', 'name')
					      ->searchable(['name'])
					      ->preload()
					      ->required()
					      ->reactive()
						  ->createOptionForm(Client::getForm())
					      ->afterStateUpdated(function ($set, $state) {
						      // Update the options for the contact_ids CheckboxList based on the selected client
						      $set('contact_ids', []); // Clear the selected contacts when the client changes
						      $contacts = Contact::where('client_id', $state)->pluck('last_name', 'id');
						      $set('contact_ids.options', $contacts); // Update the options for the CheckboxList
					      }),

But this gives no results. Can anyone point me in the right direction?

0 likes
4 replies
LaryAI's avatar
Level 58

It looks like you're on the right track with using the afterStateUpdated callback to update the options for the CheckboxList. However, the way you're trying to update the options for contact_ids is not correct. You should use the get method on the CheckboxList to retrieve the component and then call the options method to update its options.

Here's how you can modify your Select::make('client_id') to update the CheckboxList options dynamically:

Select::make('client_id')
    ->relationship('client', 'name')
    ->searchable(['name'])
    ->preload()
    ->required()
    ->reactive()
    ->createOptionForm(Client::getForm())
    ->afterStateUpdated(function (Closure $set, $state, $livewire) {
        // Clear the selected contacts when the client changes
        $set('contact_ids', []);

        // Retrieve contacts based on the selected client
        $contacts = Contact::where('client_id', $state)->pluck('name', 'id')->toArray();

        // Update the options for the CheckboxList
        $livewire->form->get('contact_ids')->options($contacts);
    }),

Make sure to replace 'name' with the actual attribute of the Contact model you want to display in the checkbox list.

Also, note that I've added a third parameter $livewire to the callback function. This is the instance of the Livewire component, which allows you to access the form and its fields.

The pluck method is used to get a collection of name and id pairs from the Contact model, which are then converted to an array with toArray() and passed to the options method of the CheckboxList.

Make sure that the name attribute in the pluck method call corresponds to the attribute you want to display for each contact in the checkbox list. If you want to display the full name or a combination of first and last names, you might need to adjust your query or use a different method to retrieve the desired display value.

El Klo's avatar
Level 11

Thank you, Lary. But this gives the following error: Method Filament\Forms\Form::get does not exist.

If anyone else might have some ideas...

El Klo's avatar
Level 11

I managed to get it working with the following code:

Select::make('client_id')
	->reactive()
	->afterStateUpdated(function ($set, $state) {	
	  $contacts = Contact::where('client_id', $state)->pluck('email', 'id')->toArray();
	  $set('contactsOptions', $contacts);
}),

CheckboxList::make('contact_ids')
							->label('Kopie verzenden naar:')
					            ->reactive()
					            ->options(fn($get) => $get('contactsOptions') ?: [])
					            ->columns(1),
2 likes

Please or to participate in this conversation.