# Filament - Forms/Fields/Select
Source: https://filamentphp.com/docs/3.x/forms/fields/select
#Overview
---------
 
Select Input
Watch the Rapid Laravel Development with Filament series on Laracasts - it will teach you the basics of adding select fields to Filament forms.
Play Video

Kevin McKee
Instructor
The select component allows you to select from a list of predefined options:
```php
use Filament\Forms\Components\Select;
Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
```
 
#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:
```php
use Filament\Forms\Components\Select;
Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->native(false)
```
 
#Searching options
------------------
You may enable a search input to allow easier access to many options, using the `searchable()` method:
```php
use Filament\Forms\Components\Select;
Select::make('author_id')
->label('Author')
->options(User::all()->pluck('name', 'id'))
->searchable()
```
 
### #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:
```php
Select::make('author_id')
->searchable()
->getSearchResultsUsing(fn (string $search): array => User::where('name', 'like', "%{$search}%")->limit(50)->pluck('name', 'id')->toArray())
->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name),
```
#Multi-select
-------------
The `multiple()` method on the `Select` component allows you to select multiple values from the list of options:
```php
use Filament\Forms\Components\Select;
Select::make('technologies')
->multiple()
->options([
'tailwind' => 'Tailwind CSS',
'alpine' => 'Alpine.js',
'laravel' => 'Laravel',
'livewire' => 'Laravel Livewire',
])
```
 
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:
```php
use Illuminate\Database\Eloquent\Model;
class App extends Model
{
protected $casts = [
'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:
```php
Select::make('technologies')
->multiple()
->searchable()
->getSearchResultsUsing(fn (string $search): array => Technology::where('name', 'like', "%{$search}%")->limit(50)->pluck('name', 'id')->toArray())
->getOptionLabelsUsing(fn (array $values): array => Technology::whereIn('id', $values)->pluck('name', 'id')->toArray()),
```
#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:
```php
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
------------------------------------------
> If you’re building a form inside your Livewire component, make sure you have set up the form’s model. Otherwise, Filament doesn’t know which model to use to retrieve the relationship from.
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:
```php
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:
```php
use Filament\Forms\Components\Select;
Select::make('technologies')
->multiple()
->relationship(titleAttribute: 'name')
```
When using `disabled()` with `multiple()` and `relationship()`, ensure that `disabled()` is called before `relationship()`. This ensures that the `dehydrated()` call from within `relationship()` is not overridden by the call from `disabled()`:
```php
use Filament\Forms\Components\Select;
Select::make('technologies')
->multiple()
->disabled()
->relationship(titleAttribute: 'name')
```
### #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:
```php
use Filament\Forms\Components\Select;
Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->searchable()
->preload()
```
### #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:
```php
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:
```php
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(),
)
```
If you would like to access the current search query in the `modifyQueryUsing` function, you can inject `$search`.
### #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:
```php
$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
```
```php
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:
```php
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'])
```
### #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:
```php
use Filament\Forms\Components\Select;
Select::make('primaryTechnologies')
->relationship(name: 'technologies', titleAttribute: 'name')
->multiple()
->pivotData([
'is_primary' => true,
])
```
### #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:
```php
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(),
]),
```
 
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:
```php
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();
}),
```
### #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:
```php
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(),
]),
```
 
The form opens in a modal, where the user can fill it with data. Upon form submission, the data from the form is saved back to the record.
 
### #Handling `MorphTo` relationships
`MorphTo` relationships are special, since they give the user the ability to select records from a range of different models. Because of this, we have a dedicated `MorphToSelect` component which is not actually a select field, rather 2 select fields inside a fieldset. The first select field allows you to select the type, and the second allows you to select the record of that type.
To use the `MorphToSelect`, you must pass `types()` into the component, which tell it how to render options for different types:
```php
use Filament\Forms\Components\MorphToSelect;
MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->titleAttribute('name'),
MorphToSelect\Type::make(Post::class)
->titleAttribute('title'),
])
```
#### #Customizing the option labels for each morphed type
The `titleAttribute()` is used to extract the titles out of each product or post. If you’d like to customize the label of each option, you can use the `getOptionLabelFromRecordUsing()` method to transform the Eloquent model into a label:
```php
use Filament\Forms\Components\MorphToSelect;
MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->getOptionLabelFromRecordUsing(fn (Product $record): string => "{$record->name} - {$record->slug}"),
MorphToSelect\Type::make(Post::class)
->titleAttribute('title'),
])
```
#### #Customizing the relationship query for each morphed type
You may customize the database query that retrieves options using the `modifyOptionsQueryUsing()` method:
```php
use Filament\Forms\Components\MorphToSelect;
use Illuminate\Database\Eloquent\Builder;
MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->titleAttribute('name')
->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
MorphToSelect\Type::make(Post::class)
->titleAttribute('title')
->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
])
```
> Many of the same options in the select field are available for `MorphToSelect`, including `searchable()`, `preload()`, `native()`, `allowHtml()`, and `optionsLimit()`.
#Allowing HTML in the option labels
-----------------------------------
By default, Filament will escape any HTML in the option labels. If you’d like to allow HTML, you can use the `allowHtml()` method:
```php
use Filament\Forms\Components\Select;
Select::make('technology')
->options([
'tailwind' => '<span class="text-blue-500">Tailwind</span>',
'alpine' => '<span class="text-green-500">Alpine</span>',
'laravel' => '<span class="text-red-500">Laravel</span>',
'livewire' => '<span class="text-pink-500">Livewire</span>',
])
->searchable()
->allowHtml()
```
Be aware that you will need to ensure that the HTML is safe to render, otherwise your application will be vulnerable to XSS attacks.
#Disable placeholder selection
------------------------------
You can prevent the placeholder (null option) from being selected using the `selectablePlaceholder()` method:
```php
use Filament\Forms\Components\Select;
Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->default('draft')
->selectablePlaceholder(false)
```
#Disabling specific options
---------------------------
You can disable specific options using the `disableOptionWhen()` method. It accepts a closure, in which you can check if the option with a specific `$value` should be disabled:
```php
use Filament\Forms\Components\Select;
Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->default('draft')
->disableOptionWhen(fn (string $value): bool => $value === 'published')
```
If you want to retrieve the options that have not been disabled, e.g. for validation purposes, you can do so using `getEnabledOptions()`:
```php
use Filament\Forms\Components\Select;
Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->default('draft')
->disableOptionWhen(fn (string $value): bool => $value === 'published')
->in(fn (Select $component): array => array_keys($component->getEnabledOptions()))
```
#Adding affix text aside the field
----------------------------------
You may place text before and after the input using the `prefix()` and `suffix()` methods:
```php
use Filament\Forms\Components\Select;
Select::make('domain')
->prefix('https://')
->suffix('.com')
```
 
### #Using icons as affixes
You may place an icon before and after the input using the `prefixIcon()` and `suffixIcon()` methods:
```php
use Filament\Forms\Components\Select;
Select::make('domain')
->suffixIcon('heroicon-m-globe-alt')
```
 
#### #Setting the affix icon’s color
Affix icons are gray by default, but you may set a different color using the `prefixIconColor()` and `suffixIconColor()` methods:
```php
use Filament\Forms\Components\Select;
Select::make('domain')
->suffixIcon('heroicon-m-check-circle')
->suffixIconColor('success')
```
#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:
```php
use Filament\Forms\Components\Select;
Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->searchable()
->loadingMessage('Loading authors...')
```
#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:
```php
use Filament\Forms\Components\Select;
Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->searchable()
->noSearchResultsMessage('No authors found.')
```
#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:
```php
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')
```
#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:
```php
use Filament\Forms\Components\Select;
Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->searchable()
->searchingMessage('Searching authors...')
```
#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:
```php
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.
#Limiting the number of options
-------------------------------
You can limit the number of options that are displayed in a searchable select or multi-select using the `optionsLimit()` method. The default is 50:
```php
use Filament\Forms\Components\Select;
Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->searchable()
->optionsLimit(20)
```
Ensure that you are not raising the limit too high, as this may cause the select to become slow and unresponsive due to high in-browser memory usage.
#Select validation
------------------
As well as all rules listed on the validation page, there are additional rules that are specific to selects.
### #Selected items validation
You can validate the minimum and maximum number of items that you can select in a multi-select by setting the `minItems()` and `maxItems()` methods:
```php
use Filament\Forms\Components\Select;
Select::make('technologies')
->multiple()
->options([
'tailwind' => 'Tailwind CSS',
'alpine' => 'Alpine.js',
'laravel' => 'Laravel',
'livewire' => 'Laravel Livewire',
])
->minItems(1)
->maxItems(3)
```
#Customizing the select action objects
--------------------------------------
This field uses action objects for easy customization of buttons within it. You can customize these buttons by passing a function to an action registration method. The function has access to the `$action` object, which you can use to customize it or customize its modal. The following methods are available to customize the actions:
* `createOptionAction()`
* `editOptionAction()`
* `manageOptionActions()` (for customizing both the create and edit option actions at once)
Here is an example of how you might customize an action:
```php
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\Select;
Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->createOptionAction(
fn (Action $action) => $action->modalWidth('3xl'),
)
```
Edit on GitHub
Still need help? Join our Discord community or open a GitHub discussion