Saltar al contenido principal

Select

Introducción

El componente select te permite elegir de una lista de opciones predefinidas:

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un array estático, el método options() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Habilitar el select en JavaScript

Por defecto, Filament usa el select nativo de HTML5. Puedes habilitar un select en JavaScript más personalizable usando el método native(false):

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método native() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Buscar opciones

Puedes habilitar un input de búsqueda para facilitar el acceso a muchas opciones usando el método searchable():

use Filament\Forms\Components\Select;

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

Opcionalmente, puedes pasar un valor booleano para controlar si el input debe ser buscable o no:

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método searchable() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Devolver resultados de búsqueda personalizados

Si tienes muchas opciones y quieres poblarlas en base a una búsqueda en base de datos u otra fuente externa, puedes usar los métodos getSearchResultsUsing() y getOptionLabelUsing() en lugar de options().

El método getSearchResultsUsing() acepta un callback que devuelve resultados de búsqueda en formato $key => $value. La búsqueda del usuario actual está disponible como $search, y debes usarla para filtrar tus resultados.

El método getOptionLabelUsing() acepta un callback que transforma la opción seleccionada $value en una etiqueta. Se usa cuando el formulario se carga por primera vez y el usuario aún no ha buscado. De lo contrario, no estaría disponible la etiqueta para mostrar la opción seleccionada actualmente.

Ambos getSearchResultsUsing() y getOptionLabelUsing() deben usarse en el select si quieres proporcionar resultados de búsqueda personalizados:

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() es crucial, ya que proporciona a Filament la etiqueta de la opción seleccionada, por lo que no necesita ejecutar una búsqueda completa para encontrarla. Si una opción no es válida, debe devolver null.

Details

Inyección de utilidades Puedes inyectar varias utilidades en estas funciones como parámetros.

Establecer un mensaje de carga personalizado

Cuando usas un select o multi-select con búsqueda, puedes mostrar un mensaje personalizado mientras se cargan las opciones usando loadingMessage():

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método loadingMessage() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Establecer un mensaje de "sin resultados"

Cuando usas un select o multi-select con búsqueda, puedes mostrar un mensaje personalizado cuando no se encuentran resultados con noSearchResultsMessage():

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método noSearchResultsMessage() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Establecer un mensaje de sugerencia de búsqueda

Cuando usas un select o multi-select con búsqueda, puedes mostrar un mensaje personalizado cuando el usuario aún no ha introducido un término de búsqueda usando searchPrompt():

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')
Details

Inyección de utilidades Además de permitir un valor estático, el método searchPrompt() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Establecer un mensaje de "buscando"

Cuando usas un select o multi-select con búsqueda, puedes mostrar un mensaje personalizado mientras se cargan los resultados con searchingMessage():

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método searchingMessage() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Ajustar el debounce de búsqueda

Por defecto, Filament esperará 1000 milisegundos (1 segundo) antes de buscar opciones cuando el usuario teclee en un select o multi-select con búsqueda. También esperará 1000 ms entre búsquedas si el usuario sigue escribiendo. Puedes cambiarlo con searchDebounce():

use Filament\Forms\Components\Select;

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

Asegúrate de no bajarlo demasiado, ya que puede volver el select lento e irresponsive por el alto número de solicitudes.

Details

Inyección de utilidades Además de permitir un valor estático, el método searchDebounce() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Multi-select

El método multiple() en el componente Select te permite seleccionar múltiples valores de la lista de opciones:

use Filament\Forms\Components\Select;

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

Opcionalmente, puedes pasar un booleano para controlar si el input debe permitir múltiples valores o no:

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método multiple() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Estas opciones se devuelven en formato JSON. Si las guardas con Eloquent, asegúrate de añadir un cast array a la propiedad del modelo:

use Illuminate\Database\Eloquent\Model;

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

// ...
}

Si estás devolviendo resultados de búsqueda personalizados, debes definir getOptionLabelsUsing() en lugar de getOptionLabelUsing(). Se pasará $values al callback en lugar de $value, y debes devolver un array $key => $value de etiquetas y sus valores correspondientes:

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() es crucial, ya que proporciona a Filament las etiquetas de las opciones ya seleccionadas, por lo que no necesita ejecutar una búsqueda completa para encontrarlas. También se usa para validar que las opciones seleccionadas por el usuario sean válidas. Si una opción no es válida, no debe estar presente en el array devuelto por getOptionLabelsUsing().

Details

Inyección de utilidades El método getOptionLabelsUsing() puede inyectar varias utilidades en la función como parámetros.

Agrupar opciones

Puedes agrupar opciones bajo una etiqueta para organizarlas mejor. Para ello, puedes pasar un array de grupos a options() o donde normalmente pasarías un array de opciones. Las claves del array se usan como etiquetas de grupo, y los valores son arrays de opciones dentro de ese grupo:

use Filament\Forms\Components\Select;

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

Integración con una relación de Eloquent

Puedes usar el método relationship() de Select para configurar una relación BelongsTo desde la que recuperar opciones automáticamente. titleAttribute es el nombre de la columna que se usará para generar la etiqueta de cada opción:

use Filament\Forms\Components\Select;

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

El método multiple() puede usarse junto con relationship() para usar una relación BelongsToMany. Filament cargará las opciones de la relación y las guardará en la tabla pivote al enviar el formulario. Si no se proporciona name, Filament usará el nombre del campo como nombre de la relación:

use Filament\Forms\Components\Select;

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

Al usar disabled() con multiple() y relationship(), asegúrate de llamar a disabled() antes que a relationship(). Esto garantiza que la llamada a dehydrated() desde relationship() no sea sobrescrita por la llamada desde disabled():

use Filament\Forms\Components\Select;

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

Buscar opciones de la relación en múltiples columnas

Por defecto, si el select también es buscable, Filament devolverá resultados de la relación basados en la columna de título. Si deseas buscar en múltiples columnas, puedes pasar un array de columnas a searchable():

use Filament\Forms\Components\Select;

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

Precargar opciones de la relación

Si deseas poblar las opciones buscables desde la base de datos al cargar la página, en lugar de cuando el usuario busque, puedes usar preload():

use Filament\Forms\Components\Select;

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

Opcionalmente, puedes pasar un booleano para controlar si el input debe precargarse o no:

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método preload() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Excluir el registro actual

Al trabajar con relaciones recursivas, probablemente quieras eliminar el registro actual de los resultados.

Esto puede hacerse fácilmente usando el argumento ignoreRecord:

use Filament\Forms\Components\Select;

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

Personalizar la consulta de la relación

Puedes personalizar la consulta que recupera opciones usando el tercer parámetro de relationship():

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(),
)
Details

Inyección de utilidades El argumento modifyQueryUsing puede inyectar varias utilidades en la función como parámetros.

Personalizar las etiquetas de opciones de la relación

Si deseas personalizar la etiqueta de cada opción, por ejemplo para que sea más descriptiva o concatenar nombre y apellido, puedes usar una columna virtual en tu migración:

$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')

Alternativamente, puedes usar getOptionLabelFromRecordUsing() para transformar el modelo Eloquent de una opción en una etiqueta:

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'])
Details

Inyección de utilidades El método getOptionLabelFromRecordUsing() puede inyectar varias utilidades en la función como parámetros.

Guardar datos pivote en la relación

Si usas una relación multiple() y tu tabla pivote tiene columnas adicionales, puedes usar pivotData() para especificar los datos que deben guardarse en ellas:

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método pivotData() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Crear una nueva opción en un modal

Puedes definir un formulario personalizado que se usará para crear un nuevo registro y adjuntarlo a la relación BelongsTo:

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(),
]),
Details

Inyección de utilidades Además de permitir un valor estático, el método createOptionForm() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

El formulario se abre en un modal, donde el usuario puede rellenarlo. Al enviar el formulario, el nuevo registro es seleccionado por el campo.

Personalizar la creación de nuevas opciones

Puedes personalizar el proceso de creación de la nueva opción definida en el formulario usando createOptionUsing(), que debe devolver la clave primaria del nuevo registro:

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();
}),
Details

Inyección de utilidades El método createOptionUsing() puede inyectar varias utilidades en la función como parámetros.

Editar la opción seleccionada en un modal

Puedes definir un formulario personalizado que se usará para editar el registro seleccionado y guardarlo de nuevo en la relación BelongsTo:

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(),
]),
Details

Inyección de utilidades Además de permitir un valor estático, el método editOptionForm() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

El formulario se abre en un modal, donde el usuario puede rellenarlo. Al enviar el formulario, los datos del formulario se guardan de nuevo en el registro.

Personalizar actualizaciones de opciones

Puedes personalizar el proceso de actualización de la opción seleccionada definida en el formulario usando updateOptionUsing(). El registro Eloquent actual que se está editando puede obtenerse usando getRecord() en el schema:

use Filament\Forms\Components\Select;
use Filament\Schemas\Schema;

Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->editOptionForm([
// ...
])
->updateOptionUsing(function (array $data, Schema $schema) {
$schema->getRecord()?->update($data);
}),
Details

Inyección de utilidades El método updateOptionUsing() puede inyectar varias utilidades en la función como parámetros.

Manejar relaciones MorphTo

Las relaciones MorphTo son especiales, ya que permiten seleccionar registros de varios modelos diferentes. Por ello, tenemos un componente dedicado MorphToSelect que en realidad no es un campo select único, sino 2 selects dentro de un fieldset. El primer select permite elegir el tipo, y el segundo permite seleccionar el registro de ese tipo.

Para usar MorphToSelect, debes pasar types() al componente, que le indica cómo renderizar opciones para diferentes tipos:

use Filament\Forms\Components\MorphToSelect;

MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->titleAttribute('name'),
MorphToSelect\Type::make(Post::class)
->titleAttribute('title'),
])
Details

Inyección de utilidades El método types() puede inyectar varias utilidades en la función como parámetros.

Personalizar las etiquetas de opción para cada tipo morph

titleAttribute() se usa para extraer los títulos de cada producto o post. Si deseas personalizar la etiqueta de cada opción, puedes usar getOptionLabelFromRecordUsing() para transformar el modelo Eloquent en una etiqueta:

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'),
])

Personalizar la consulta de relación para cada tipo morph

Puedes personalizar la consulta que recupera opciones usando modifyOptionsQueryUsing():

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)),
])
Details

Inyección de utilidades El método modifyOptionsQueryUsing() puede inyectar varias utilidades en la función como parámetros.

tip

Muchas de las mismas opciones del campo select están disponibles para MorphToSelect, incluyendo searchable(), preload(), native(), allowHtml() y optionsLimit().

Personalizar los selects del morph

Puedes personalizar aún más el select de "clave" para un tipo morph específico usando modifyKeySelectUsing():

use Filament\Forms\Components\MorphToSelect;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;

MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->titleAttribute('name')
->modifyKeySelectUsing(fn (Select $select): Select => $select
->createOptionForm([
TextInput::make('title')
->required(),
])
->createOptionUsing(function (array $data): int {
return Product::create($data)->getKey();
})),
MorphToSelect\Type::make(Post::class)
->titleAttribute('title'),
])

Esto es útil si quieres personalizar el select de "clave" para cada tipo morph individualmente. Si quieres personalizar la clave para todos los tipos, puedes usar modifyKeySelectUsing() en el propio componente MorphToSelect:

use Filament\Forms\Components\MorphToSelect;
use Filament\Forms\Components\Select;

MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->titleAttribute('name'),
MorphToSelect\Type::make(Post::class)
->titleAttribute('title'),
])
->modifyKeySelectUsing(fn (Select $select): Select => $select->native())

También puedes modificar el select de "tipo" usando modifyTypeSelectUsing():

use Filament\Forms\Components\MorphToSelect;
use Filament\Forms\Components\Select;

MorphToSelect::make('commentable')
->types([
MorphToSelect\Type::make(Product::class)
->titleAttribute('name'),
MorphToSelect\Type::make(Post::class)
->titleAttribute('title'),
])
->modifyTypeSelectUsing(fn (Select $select): Select => $select->native())

Permitir HTML en las etiquetas de opción

Por defecto, Filament escapará cualquier HTML en las etiquetas de opción. Si deseas permitir HTML, puedes usar allowHtml():

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()
peligro

Debes asegurarte de que el HTML sea seguro de renderizar; de lo contrario, tu aplicación será vulnerable a ataques XSS.

Opcionalmente, puedes pasar un booleano para controlar si el input debe permitir HTML o no:

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(FeatureFlag::active())
Details

Inyección de utilidades Además de permitir un valor estático, el método allowHtml() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Ajustar o truncar etiquetas de opción

Cuando usas el select en JavaScript, las etiquetas que exceden el ancho del elemento se ajustan en varias líneas por defecto. Alternativamente, puedes truncar las etiquetas desbordadas.

use Filament\Forms\Components\Select;

Select::make('truncate')
->wrapOptionLabels(false)
Details

Inyección de utilidades Además de permitir un valor estático, el método wrapOptionLabels() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Deshabilitar la selección del placeholder

Puedes evitar que el placeholder (opción nula) sea seleccionable usando selectablePlaceholder(false):

use Filament\Forms\Components\Select;

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

Inyección de utilidades Además de permitir un valor estático, el método selectablePlaceholder() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Deshabilitar opciones específicas

Puedes deshabilitar opciones específicas usando disableOptionWhen(). Acepta un closure en el que puedes comprobar si la opción con un $value concreto debe deshabilitarse:

use Filament\Forms\Components\Select;

Select::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->default('draft')
->disableOptionWhen(fn (string $value): bool => $value === 'published')
Details

Inyección de utilidades Puedes inyectar varias utilidades en la función como parámetros.

Añadir texto de prefijo/sufijo junto al campo

Puedes colocar texto antes y después del input usando prefix() y suffix():

use Filament\Forms\Components\Select;

Select::make('domain')
->prefix('https://')
->suffix('.com')
Details

Inyección de utilidades Además de permitir valores estáticos, los métodos prefix() y suffix() también aceptan una función para calcularlos dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Usar iconos como prefijos/sufijos

Puedes colocar un icono antes y después del input usando prefixIcon() y suffixIcon():

use Filament\Forms\Components\Select;
use Filament\Support\Icons\Heroicon;

Select::make('domain')
->suffixIcon(Heroicon::GlobeAlt)
Details

Inyección de utilidades Además de permitir valores estáticos, los métodos prefixIcon() y suffixIcon() también aceptan una función para calcularlos dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Establecer el color del icono de prefijo/sufijo

Los iconos de prefijo/sufijo son grises por defecto, pero puedes establecer otro color usando prefixIconColor() y suffixIconColor():

use Filament\Forms\Components\Select;
use Filament\Support\Icons\Heroicon;

Select::make('domain')
->suffixIcon(Heroicon::CheckCircle)
->suffixIconColor('success')
Details

Inyección de utilidades Además de permitir valores estáticos, los métodos prefixIconColor() y suffixIconColor() también aceptan una función para calcularlos dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Limitar el número de opciones

Puedes limitar el número de opciones que se muestran en un select o multi-select con búsqueda usando optionsLimit(). El valor por defecto es 50:

use Filament\Forms\Components\Select;

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

Asegúrate de no subir el límite demasiado, ya que puede volver el select lento y poco responsivo por el alto uso de memoria en el navegador.

Details

Inyección de utilidades Además de permitir un valor estático, el método optionsLimit() también acepta una función para calcularlo dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Opciones booleanas

Si quieres un select booleano simple, con opciones "Yes" y "No", puedes usar boolean():

use Filament\Forms\Components\Select;

Select::make('feedback')
->label('Like this post?')
->boolean()

Para personalizar la etiqueta de "Yes", puedes usar el argumento trueLabel en boolean():

use Filament\Forms\Components\Select;

Select::make('feedback')
->label('Like this post?')
->boolean(trueLabel: 'Absolutely!')

Para personalizar la etiqueta de "No", puedes usar el argumento falseLabel en boolean():

use Filament\Forms\Components\Select;

Select::make('feedback')
->label('Like this post?')
->boolean(falseLabel: 'Not at all!')

Para personalizar el placeholder que se muestra cuando aún no se ha seleccionado una opción, puedes usar el argumento placeholder en boolean():

use Filament\Forms\Components\Select;

Select::make('feedback')
->label('Like this post?')
->boolean(placeholder: 'Make your mind up...')

Seleccionar opciones desde una tabla en un modal

Puedes usar el componente ModalTableSelect para abrir una tabla de Filament en un modal, permitiendo a los usuarios seleccionar registros de ella. Esto es útil cuando tienes una relación con muchos registros y quieres permitir filtrado y búsqueda avanzados.

Para usar ModalTableSelect, debes tener una clase de configuración de tabla para el modelo. Puedes generar una usando el comando make:filament-table:

use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;

class CategoriesTable
{
public static function configure(Table $table): Table
{
return $table
->columns([
TextColumn::make('name')
->searchable(),
TextColumn::make('slug')
->searchable(),
])
->filters([
SelectFilter::make('parent')
->relationship('parent', 'name')
->searchable()
->preload(),
]);
}
}

La clase debe tener un método configure() que acepte el objeto Table y lo devuelva. El nombre de la clase debe pasarse al método tableConfiguration() del componente ModalTableSelect:

use Filament\Forms\Components\ModalTableSelect;

ModalTableSelect::make('category_id')
->relationship('category', 'name')
->tableConfiguration(CategoriesTable::class)

También puedes usar el método multiple() con una relación múltiple como BelongsToMany:

use Filament\Forms\Components\ModalTableSelect;

ModalTableSelect::make('categories')
->relationship('categories', 'name')
->multiple()
->tableConfiguration(CategoriesTable::class)
Details

Inyección de utilidades El método tableConfiguration() puede inyectar varias utilidades en la función como parámetros.

Personalizar las acciones del modal table select

Puedes personalizar el botón "Select" y el modal usando los métodos de configuración de acciones. Pasar una función a selectAction() te permite modificar el objeto $action, por ejemplo, para cambiar la etiqueta del botón y el encabezado del modal:

use Filament\Actions\Action;
use Filament\Forms\Components\ModalTableSelect;

ModalTableSelect::make('category_id')
->relationship('category', 'name')
->tableConfiguration(CategoriesTable::class)
->selectAction(
fn (Action $action) => $action
->label('Select a category')
->modalHeading('Search categories')
->modalSubmitActionLabel('Confirm selection'),
)
Details

Inyección de utilidades El método selectAction() puede inyectar varias utilidades en la función como parámetros.

Personalizar las etiquetas de opción en el modal table select

El método getOptionLabelFromRecordUsing() puede usarse para personalizar la etiqueta de cada opción seleccionada. Es útil si quieres mostrar una etiqueta más descriptiva o concatenar dos columnas:

use Filament\Forms\Components\ModalTableSelect;

ModalTableSelect::make('category_id')
->relationship('category', 'name')
->tableConfiguration(CategoriesTable::class)
->getOptionLabelFromRecordUsing(fn (Category $record): string => "{$record->name} ({$record->slug})")

Pasar argumentos adicionales a la tabla del modal select

Puedes pasar argumentos desde tu formulario a la clase de configuración de la tabla usando tableArguments(). Por ejemplo, puedes modificar la consulta de la tabla en base a campos llenados previamente:

use Filament\Actions\Action;
use Filament\Forms\Components\ModalTableSelect;
use Filament\Schemas\Components\Utilities\Get;

ModalTableSelect::make('products')
->relationship('products', 'name')
->multiple()
->tableConfiguration(ProductsTable::class)
->tableArguments(function (Get $get): array {
return [
'category_id' => $get('category_id'),
'budget_limit' => $get('budget'),
];
})
Details

Inyección de utilidades El método tableArguments() puede inyectar varias utilidades en la función como parámetros.

En tu clase de configuración de tabla, puedes acceder a estos argumentos usando $table->getArguments():

use Filament\Forms\Components\TableSelect\Livewire\TableSelectLivewireComponent;
use Filament\Tables\Columns\TextColumn;
use Illuminate\Database\Eloquent\Builder;
use Filament\Tables\Table;

class ProductsTable
{
public static function configure(Table $table): Table
{
return $table
->modifyQueryUsing(function (Builder $query) use ($table): Builder {
$arguments = $table->getArguments();

if ($categoryId = $arguments['category_id'] ?? null) {
$query->where('category_id', $categoryId);
}

if ($budgetLimit = $arguments['budget_limit'] ?? null) {
$query->where('price', '<=', $budgetLimit);
}

return $query;
})
->columns([
TextColumn::make('name'),
TextColumn::make('price')
->money(),
TextColumn::make('category.name')
->hidden(filled($table->getArguments()['category_id'])),
]);
}
}

Validación del select

Además de todas las reglas listadas en la página de validación, hay reglas adicionales específicas de los selects.

Validación de opciones válidas (regla in())

La regla in() asegura que los usuarios no puedan seleccionar una opción que no esté en la lista de opciones. Es una regla importante para la integridad de datos, por lo que Filament la aplica por defecto a todos los campos select.

aviso

La validación de la opción seleccionada es crucial, por lo que recomendamos encarecidamente que escribas tests automatizados para tus formularios y asegurar que la validación funciona como se espera.

Dado que hay muchas formas para que un select pueble sus opciones, y en muchos casos las opciones no se cargan todas por defecto y requieren búsqueda, Filament usa la presencia de una "etiqueta de opción" válida para determinar si el valor seleccionado existe. También comprueba si esa opción está deshabilitada o no.

Si estás usando una búsqueda personalizada para recuperar opciones, debes asegurarte de definir getOptionLabelUsing(), para que Filament pueda validar el valor seleccionado frente a las opciones disponibles:

use Filament\Forms\Components\Select;

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

El método getOptionLabelUsing() debe devolver null si la opción no es válida, para permitir a Filament determinar que el valor seleccionado no está en la lista de opciones. Si la opción es válida, debe devolver la etiqueta de la opción.

Si usas un select multiple() o multi-select, debes definir getOptionLabelsUsing() en lugar de getOptionLabelUsing(). Se pasará $values al callback en lugar de $value, y debes devolver un array $key => $value de etiquetas y sus valores correspondientes:

use Filament\Forms\Components\Select;

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()),

Si usas el método relationship(), los métodos getOptionLabelUsing() o getOptionLabelsUsing() se definirán automáticamente por ti, por lo que no necesitas preocuparte por ellos.

Validación del número de elementos seleccionados

Puedes validar el número mínimo y máximo de elementos seleccionables en un multi-select con los métodos minItems() y maxItems():

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)
Details

Inyección de utilidades Además de permitir valores estáticos, los métodos minItems() y maxItems() también aceptan una función para calcularlos dinámicamente. Puedes inyectar varias utilidades en la función como parámetros.

Personalizar los objetos de acción del select

Este campo usa objetos de acción para facilitar la personalización de los botones dentro de él. Puedes personalizar estos botones pasando una función a un método de registro de acciones. La función tiene acceso al objeto $action, que puedes usar para personalizarlo o personalizar su modal. Los siguientes métodos están disponibles para personalizar las acciones:

  • createOptionAction()
  • editOptionAction()
  • manageOptionActions() (para personalizar las acciones de crear y editar a la vez)

Aquí hay un ejemplo de cómo podrías personalizar una acción:

use Filament\Actions\Action;
use Filament\Forms\Components\Select;

Select::make('author_id')
->relationship(name: 'author', titleAttribute: 'name')
->createOptionAction(
fn (Action $action) => $action->modalWidth('3xl'),
)
Details

Inyección de utilidades Los métodos de registro de acciones pueden inyectar varias utilidades en la función como parámetros.