UISelect
es un
select
nativo con
appearance: base-select: el navegador trae la lista, el teclado y el valor de formulario, y UI la pinta con sus tokens.
UICombobox
cubre lo que el nativo no puede: buscar, filtrar en un servidor y elegir varias opciones. El tipo del modelo se infiere de
options.
Una opción en un formulario
Con
name, el valor se envía con un formulario nativo sin código adicional. Abre la lista con
Intro,
Espacio
o un clic y escribe una letra para saltar a la opción que empieza por ella: es el teclado del navegador.
<script lang="ts">
const plans = ['Personal', 'Equipo', 'Empresa', 'Educación']
const topics = ['Accesibilidad', 'Diseño', 'Documentación', 'Rendimiento']
const plan = signal<string | null>(null)
const chosen = signal<string[]>([])
</script>
<template>
<form method="post" action="/subscriptions">
<label for="plan">Plan</label>
<UISelect id="plan" model="plan" bind:options="plans"
name="plan" placeholder="Elige un plan" required />
<label for="topics">Temas</label>
<UICombobox id="topics" model="chosen" bind:options="topics"
name="topics" multiple searchable bind:max="2" />
<UIButton type="submit">Enviar selección</UIButton>
</form>
</template>required, un formulario sin valor no se envía: el
select
recibe el foco y
aria-invalid, sin el aviso del navegador. Escribe además un mensaje visible con
UIField, como en el ejemplo. Con
useForm, pasa
bind:field="form.field('plan')"
y el campo aporta el id, el nombre, el valor y el estado de error.
Navegadores
Chrome, Edge y Safari 27 pintan la lista con los tokens de UI, con entrada animada. Firefox y los navegadores antiguos muestran su lista propia: funcionan igual, y en ellos
value,
group
y el contenido rico de
option
quedan en su texto. Una opción oculta al principio representa el
placeholder, o un valor que ya no está en
options: el modelo lo conserva y el formulario lo sigue enviando.
Objetos, grupos y opciones propias
Las opciones pueden ser objetos.
by
decide cómo se comparan,
labelBy
qué texto se muestra y se busca,
groupBy
añade un encabezado por grupo y una opción con
disabled: true
no se puede elegir. Los snippets
option
y
value
reciben la opción con su tipo.
Sin responsable asignado.
<script lang="ts">
interface Member { id: number; name: string; team: string; role: string; disabled?: boolean }
const members: Member[] = [
{ id: 1, name: 'Lucía Martín', team: 'Diseño', role: 'Directora de arte' },
{ id: 4, name: 'Mateo Gil', team: 'Ingeniería', role: 'De vacaciones', disabled: true },
]
const owner = signal<Member | null>(null)
</script>
<template>
<UISelect model="owner" bind:options="members" by="id"
labelBy="name" groupBy="team" label="Responsable" clearable>
<snippet name="option" params="member, state">
<strong>{member.name}</strong>
<small>{state.disabled ? 'No disponible' : member.role}</small>
</snippet>
</UISelect>
</template>API de UISelect
| Nombre | Tipo / valor inicial | Descripción |
|---|---|---|
options
|
readonly T[]
| Obligatoria. Primitivos u objetos. |
model
|
Signal<T | null>
null
| Valor elegido. |
by / labelBy / disabledBy / groupBy
|
clave o función
| Comparación, etiqueta, deshabilitado y grupo de cada opción. |
clearable / clearLabel
|
boolean / string
false / Quitar selección
| Botón accesible que quita la selección y devuelve el foco al select. La etiqueta por defecto sigue el idioma del documento (véase Temas). |
name / required / disabled
|
string / boolean
| Envío y validación del formulario. |
field
|
SelectField
| Un campo de useForm: id, name, valor, aria-invalid y aria-describedby. |
id / label / describedBy / invalid
|
string / boolean
| Identidad y estado accesible del select. |
placeholder
|
string
| Texto sin valor. |
placement / offset
|
PopoverPlacement / number
bottom-start
| Posición de la lista, donde el navegador la pinta con los tokens. |
class / listClass
|
string
| Clases de la raíz y del select; dale estilo a la lista con .mi-clase::picker(select). |
Admite los snippets
option,
value
y
group, y el evento
change.
multiple,
searchable,
filter
y
max
son un error de tipos que indica
UICombobox.
UICombobox
Una lista propia sobre
UIPopover, con más JavaScript: úsala sólo si necesitas
searchable,
filter,
multiple
o
max. El foco permanece en el disparador mientras
aria-activedescendant
recorre la lista. El campo Temas del primer ejemplo es un
UICombobox. Con
multiple, cada opción se alterna, la lista sigue abierta y el modelo es un array;
max
deshabilita el resto al llegar al límite.
<UICombobox id="topics" model="chosen" bind:options="topics"
name="topics" multiple searchable bind:max="2" placeholder="Busca un tema" />
Para buscar en un servidor, pasa una función
filter
que devuelva una promesa y use su
AbortSignal. Sin resultados, muestra
empty: por defecto,
Sin resultados.
| Nombre | Tipo / valor inicial | Descripción |
|---|---|---|
model
|
Signal<T | null> o Signal<T[]>
null
| Valor elegido; un array con multiple. |
multiple
|
boolean
false
| Permite elegir varias opciones. |
searchable / filter
|
boolean / ComboboxFilter<T>
| Búsqueda en la lista, síncrona o asíncrona. |
max
|
number
| Con multiple, número máximo de opciones elegidas. |
El resto de propiedades son las de
UISelect. Admite además los snippets
empty
y
loading. Los tipos
UISelectProps,
UIComboboxProps,
SelectModel
y
ComboboxFilter
se exportan desde
@meekojs/ui/runtime.