Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Forms Laravel Package

filament/forms

Filament Forms is a Laravel package for building powerful, reactive admin forms with a fluent, component-based API. Create fields, layouts, validation, conditional logic, and dynamic interactions quickly, with tight Livewire integration and great DX for panels and apps.

View on GitHub
Deep Wiki
Context7

title: Select

import Aside from "@components/Aside.astro" import AutoScreenshot from "@components/AutoScreenshot.astro" import UtilityInjection from "@components/UtilityInjection.astro"

Introduction

The select component allows you to select from a list of predefined options:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])

<UtilityInjection set="formFields" version="5.x">As well as allowing a static array, the options() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Enabling the JavaScript select

By default, Filament uses the native HTML5 select. You may enable a more customizable JavaScript select using the native(false) method:

use Filament\Forms\Components\Select;

Select::make('status')
    ->options([
        'draft' => 'Draft',
        'reviewing' => 'Reviewing',
        'published' => 'Published',
    ])
    ->native(false)

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the native() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Searching options

You may enable a search input to allow easier access to many options, using the searchable() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->label('Author')
    ->options(User::query()->pluck('name', 'id'))
    ->searchable()

Optionally, you may pass a boolean value to control if the input should be searchable or not:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->label('Author')
    ->options(User::query()->pluck('name', 'id'))
    ->searchable(FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the searchable() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Returning custom search results

If you have lots of options and want to populate them based on a database search or other external data source, you can use the getSearchResultsUsing() and getOptionLabelUsing() methods instead of options().

The getSearchResultsUsing() method accepts a callback that returns search results in $key => $value format. The current user's search is available as $search, and you should use that to filter your results.

The getOptionLabelUsing() method accepts a callback that transforms the selected option $value into a label. This is used when the form is first loaded when the user has not made a search yet. Otherwise, the label used to display the currently selected option would not be available.

Both getSearchResultsUsing() and getOptionLabelUsing() must be used on the select if you want to provide custom search results:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->searchable()
    ->getSearchResultsUsing(fn (string $search): array => User::query()
        ->where('name', 'like', "%{$search}%")
        ->limit(50)
        ->pluck('name', 'id')
        ->all())
    ->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name),

getOptionLabelUsing() is crucial, since it provides Filament with the label of the selected option, so it doesn't need to execute a full search to find it. If an option is not valid, it should return null.

<UtilityInjection set="formFields" version="5.x" extras="Option value;;mixed;;$value;;[getOptionLabelUsing() only] The option value to retrieve the label for.||Option values;;array;;$values;;[getOptionLabelsUsing() only] The option values to retrieve the labels for.||Search;;?string;;$search;;[getSearchResultsUsing() only] The current search input value, if the field is searchable.">You can inject various utilities into these functions as parameters.</UtilityInjection>

Setting a custom loading message

When you're using a searchable select or multi-select, you may want to display a custom message while the options are loading. You can do this using the loadingMessage() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable()
    ->loadingMessage('Loading authors...')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the loadingMessage() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Setting a custom no search results message

When you're using a searchable select or multi-select, you may want to display a custom message when no search results are found. You can do this using the noSearchResultsMessage() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable()
    ->noSearchResultsMessage('No authors found.')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the noSearchResultsMessage() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Setting a custom no options message

When you're using a select or multi-select with preload() or dynamic options via options() closure, you may want to display a custom message when no options are available. You can do this using the noOptionsMessage() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable()
    ->preload()
    ->noOptionsMessage('No authors available.')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the noOptionsMessage() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Setting a custom search prompt

When you're using a searchable select or multi-select, you may want to display a custom message when the user has not yet entered a search term. You can do this using the searchPrompt() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable(['name', 'email'])
    ->searchPrompt('Search authors by their name or email address')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the searchPrompt() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Setting a custom searching message

When you're using a searchable select or multi-select, you may want to display a custom message while the search results are being loaded. You can do this using the searchingMessage() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable()
    ->searchingMessage('Searching authors...')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the searchingMessage() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Tweaking the search debounce

By default, Filament will wait 1000 milliseconds (1 second) before searching for options when the user types in a searchable select or multi-select. It will also wait 1000 milliseconds between searches, if the user is continuously typing into the search input. You can change this using the searchDebounce() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable()
    ->searchDebounce(500)

Ensure that you are not lowering the debounce too much, as this may cause the select to become slow and unresponsive due to a high number of network requests to retrieve options from server.

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the searchDebounce() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Multi-select

The multiple() method on the Select component allows you to select multiple values from the list of options:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

Optionally, you may pass a boolean value to control if the input should be multiple or not:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple(FeatureFlag::active())
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the multiple() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

These options are returned in JSON format. If you're saving them using Eloquent, you should be sure to add an array cast to the model property:

use Illuminate\Database\Eloquent\Model;

class App extends Model
{
    /**
     * [@return](https://github.com/return) array<string, string>
     */
    protected function casts(): array
    {
        return [
            'technologies' => 'array',
        ];
    }

    // ...
}

If you're returning custom search results, you should define getOptionLabelsUsing() instead of getOptionLabelUsing(). $values will be passed into the callback instead of $value, and you should return a $key => $value array of labels and their corresponding values:

Select::make('technologies')
    ->multiple()
    ->searchable()
    ->getSearchResultsUsing(fn (string $search): array => Technology::query()
        ->where('name', 'like', "%{$search}%")
        ->limit(50)
        ->pluck('name', 'id')
        ->all())
    ->getOptionLabelsUsing(fn (array $values): array => Technology::query()
        ->whereIn('id', $values)
        ->pluck('name', 'id')
        ->all()),

getOptionLabelsUsing() is crucial, since it provides Filament with the labels of already-selected options, so it doesn't need to execute a full search to find them. It is also used to validate that the options that the user has selected are valid. If an option is not valid, it should not be present in the array returned by getOptionLabelsUsing().

<UtilityInjection set="formFields" version="5.x" extras="Option values;;array;;$values;;[getOptionLabelsUsing() only] The option values to retrieve the labels for.">The getOptionLabelsUsing() method can inject various utilities into the function as parameters.</UtilityInjection>

Reordering selected options

The reorderable() method allows you to reorder the selected options in a multi-select:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->reorderable()
    ->options([
        'tailwind' => 'Tailwind CSS',
        'alpine' => 'Alpine.js',
        'laravel' => 'Laravel',
        'livewire' => 'Laravel Livewire',
    ])

This is useful when the order of the selected options matters.

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the reorderable() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Grouping options

You can group options together under a label, to organize them better. To do this, you can pass an array of groups to options() or wherever you would normally pass an array of options. The keys of the array are used as group labels, and the values are arrays of options in that group:

use Filament\Forms\Components\Select;

Select::make('status')
    ->searchable()
    ->options([
        'In Process' => [
            'draft' => 'Draft',
            'reviewing' => 'Reviewing',
        ],
        'Reviewed' => [
            'published' => 'Published',
            'rejected' => 'Rejected',
        ],
    ])

Integrating with an Eloquent relationship

You may employ the relationship() method of the Select to configure a BelongsTo relationship to automatically retrieve options from. The titleAttribute is the name of a column that will be used to generate a label for each option:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')

The multiple() method may be used in combination with relationship() to use a BelongsToMany relationship. Filament will load the options from the relationship, and save them back to the relationship's pivot table when the form is submitted. If a name is not provided, Filament will use the field name as the relationship name:

use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->relationship(titleAttribute: 'name')
```php
use Filament\Forms\Components\Select;

Select::make('technologies')
    ->multiple()
    ->disabled()
    ->relationship(titleAttribute: 'name')

</Aside>

### Searching relationship options across multiple columns

By default, if the select is also searchable, Filament will return search results for the relationship based on the title column of the relationship. If you'd like to search across multiple columns, you can pass an array of columns to the `searchable()` method:

```php
use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable(['name', 'email'])

Preloading relationship options

If you'd like to populate the searchable options from the database when the page is loaded, instead of when the user searches, you can use the preload() method:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable()
    ->preload()

Optionally, you may pass a boolean value to control if the input should be preloaded or not:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->searchable()
    ->preload(FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the preload() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Excluding the current record

When working with recursive relationships, you will likely want to remove the current record from the set of results.

This can be easily be done using the ignoreRecord argument:

use Filament\Forms\Components\Select;

Select::make('parent_id')
    ->relationship(name: 'parent', titleAttribute: 'name', ignoreRecord: true)

Customizing the relationship query

You may customize the database query that retrieves options using the third parameter of the relationship() method:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Builder;

Select::make('author_id')
    ->relationship(
        name: 'author',
        titleAttribute: 'name',
        modifyQueryUsing: fn (Builder $query) => $query->withTrashed(),
    )

<UtilityInjection set="formFields" version="5.x" extras="Query;;Illuminate\Database\Eloquent\Builder;;$query;;The Eloquent query builder to modify.||Search;;?string;;$search;;The current search input value, if the field is searchable.">The modifyQueryUsing argument can inject various utilities into the function as parameters.</UtilityInjection>

Customizing the relationship option labels

If you'd like to customize the label of each option, maybe to be more descriptive, or to concatenate a first and last name, you could use a virtual column in your database migration:

$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'full_name')

Alternatively, you can use the getOptionLabelFromRecordUsing() method to transform an option's Eloquent model into a label:

use Filament\Forms\Components\Select;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

Select::make('author_id')
    ->relationship(
        name: 'author',
        modifyQueryUsing: fn (Builder $query) => $query->orderBy('first_name')->orderBy('last_name'),
    )
    ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")
    ->searchable(['first_name', 'last_name'])

<UtilityInjection set="formFields" version="5.x" extras="Eloquent record;;Illuminate\Database\Eloquent\Model;;$record;;The Eloquent record to get the option label for.">The getOptionLabelFromRecordUsing() method can inject various utilities into the function as parameters.</UtilityInjection>

Saving pivot data to the relationship

If you're using a multiple() relationship and your pivot table has additional columns, you can use the pivotData() method to specify the data that should be saved in them:

use Filament\Forms\Components\Select;

Select::make('primaryTechnologies')
    ->relationship(name: 'technologies', titleAttribute: 'name')
    ->multiple()
    ->pivotData([
        'is_primary' => true,
    ])

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the pivotData() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Creating a new option in a modal

You may define a custom form that can be used to create a new record and attach it to the BelongsTo relationship:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->createOptionForm([
        Forms\Components\TextInput::make('name')
            ->required(),
        Forms\Components\TextInput::make('email')
            ->required()
            ->email(),
    ]),

<UtilityInjection set="formFields" version="5.x" extras="Schema;;Filament\Schemas\Schema;;$schema;;The schema object for the form in the modal.">As well as allowing a static value, the createOptionForm() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

The form opens in a modal, where the user can fill it with data. Upon form submission, the new record is selected by the field.

Customizing new option creation

You can customize the creation process of the new option defined in the form using the createOptionUsing() method, which should return the primary key of the newly created record:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->createOptionForm([
       // ...
    ])
    ->createOptionUsing(function (array $data): int {
        return auth()->user()->team->members()->create($data)->getKey();
    }),

<UtilityInjection set="formFields" version="5.x" extras="Data;;array<string, mixed>;;$data;;The data from the form in the modal.||Schema;;Filament\Schemas\Schema;;$schema;;The schema object for the form in the modal.">The createOptionUsing() method can inject various utilities into the function as parameters.</UtilityInjection>

Editing the selected option in a modal

You may define a custom form that can be used to edit the selected record and save it back to the BelongsTo relationship:

use Filament\Forms\Components\Select;

Select::make('author_id')
    ->relationship(name: 'author', titleAttribute: 'name')
    ->editOptionForm([
        Forms\Components\TextInput::make('name')
            ->required(),
        Forms\Components\TextInput::make('email')
            ->required()
            ->email(),
    ]),...
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4