Saltar al contenido principal

Autocomplete remoto

Probalo en vivo​

Abrir Autocomplete remoto en el Lab →

Autocomplete local y remoto​

El Autocomplete local recibe options en su schema. Un autocomplete remoto no tiene options locales: declara un optionsSource y la aplicación consumidora entrega los datos mediante dataSourceExecutor.

El Lab usa usuarios de DummyJSON como endpoint público real. Es solamente una demostración de integración; en producción la aplicación consumidora es dueña de backend, HTTP, autenticación, autorización y caché.

optionsSource: {sourceId: 'dummyjson-users', minSearchLength: 2}

minSearchLength evita una búsqueda hasta escribir dos caracteres. DYONA Form no hace fetch automáticamente.

Búsqueda y resolución​

options.search recibe request.input.searchText. Este ejemplo llama a https://dummyjson.com/users/search con ese texto, limit=10 y los fields necesarios para el label.

options.resolve recibe request.input.value. Llama a https://dummyjson.com/users/<id> para que un ID en initialValues pueda mostrar su label antes de cualquier búsqueda.

Cada request incluye además context.fieldName, context.values y request.signal. Pasá el signal a fetch para abortar búsquedas reemplazadas y controlá response.ok antes de usar la respuesta. DYONA Form muestra estados localizados de carga y error.

Información secundaria en el dropdown​

DyonaDataSourceOption admite opcionalmente secondaryLabel:

{value: user.id, label: `${user.firstName} ${user.lastName}`, secondaryLabel: user.email}

El dropdown puede mostrar Emily Johnson y debajo [email protected]. Al seleccionar, el input muestra sólo Emily Johnson; secondaryLabel es sólo presentación y el value sigue siendo el ID. Es genérico para proveedor + CUIT, cliente + documento, usuario + email o producto + código.

Ejemplo completo​

import {useCallback, useMemo} from 'react';
import {DyonaForm, type DyonaDataSourceExecutor, type DyonaDataSourceOption, type DyonaFormSchema} from '@typhonsoftware/dyona-form';

type DummyUser = {id: number; firstName: string; lastName: string; email: string};
type DummyUsersSearchResponse = {users: DummyUser[]};
const initialValues = {customerId: 1};

function mapUserToOption(user: DummyUser): DyonaDataSourceOption {
return {value: user.id, label: `${user.firstName} ${user.lastName}`, secondaryLabel: user.email};
}

export function RemoteCustomerForm() {
const schema = useMemo<DyonaFormSchema>(() => ({
title: 'Selección de cliente',
tabs: [{id: 'customer', title: 'Cliente', rows: [{columns: [{
name: 'customerId', label: 'Cliente', type: 'autocomplete',
optionsSource: {sourceId: 'dummyjson-users', minSearchLength: 2},
}]}]}],
}), []);
const dataSourceExecutor = useCallback<DyonaDataSourceExecutor>(async (request) => {
if (request.operation === 'options.search') {
const query = new URLSearchParams({q: request.input.searchText, limit: '10', select: 'id,firstName,lastName,email'});
const response = await fetch(`https://dummyjson.com/users/search?${query}`, {signal: request.signal});
if (!response.ok) throw new Error(`La búsqueda en DummyJSON falló (HTTP ${response.status})`);
const data = await response.json() as DummyUsersSearchResponse;
return {operation: 'options.search', data: data.users.map(mapUserToOption)};
}
const response = await fetch(`https://dummyjson.com/users/${request.input.value}`, {signal: request.signal});
if (!response.ok) throw new Error(`La resolución en DummyJSON falló (HTTP ${response.status})`);
const user = await response.json() as DummyUser;
return {operation: 'options.resolve', data: mapUserToOption(user)};
}, []);
return <DyonaForm locale="es" schema={schema} initialValues={initialValues} dataSourceExecutor={dataSourceExecutor} onSubmit={(values) => console.log(values)} />;
}

El ID numérico se mantiene desde initialValues, pasando por request.input.value, hasta option.value. La comparación es estricta: no conviertas el ID a otro tipo. Al enviar, DYONA Form devuelve {customerId: 1}, no el label.

Próximos pasos​