Skip to main content

Select

A dropdown selector for choosing one or multiple values from a list.

Source: Re-exported from antd with VEF hook enhancements. Full documentation: Ant Design Select

When to Use

  • The content of the options is complex (e.g. with icons or descriptions).
  • The number of options is large and needs filtering.
  • Use Radio when there are fewer than 5 options.

Basic Usage

import { Select } from '@vef-framework-react/components';

const options = [
{ value: 'jack', label: 'Jack' },
{ value: 'lucy', label: 'Lucy' },
{ value: 'tom', label: 'Tom' },
];

export default function Demo() {
return (
<Select
style={{ width: 200 }}
placeholder="Select a person"
options={options}
onChange={(value) => console.log(value)}
/>
);
}

Multiple Selection

import { Select } from '@vef-framework-react/components';

export default function Demo() {
return (
<Select
mode="multiple"
style={{ width: '100%' }}
placeholder="Select multiple"
options={[
{ value: 'a', label: 'Option A' },
{ value: 'b', label: 'Option B' },
{ value: 'c', label: 'Option C' },
]}
/>
);
}

Searchable

import { Select } from '@vef-framework-react/components';

export default function Demo() {
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Search to select"
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
options={[
{ value: '1', label: 'Beijing' },
{ value: '2', label: 'Shanghai' },
{ value: '3', label: 'Guangzhou' },
]}
/>
);
}

VEF Enhancement: useDataOptionsSelect

VEF provides useDataOptionsSelect to load options from an async data source with built-in loading state, pinyin search support, and caching. Fetch options are nested under queryOptions (the same shape TanStack Query's useQuery accepts); useDataOptionsSelect-specific options sit alongside it.

import { Select, useDataOptionsSelect } from '@vef-framework-react/components';

async function fetchCities() {
const res = await fetch('/api/cities');
return res.json(); // returns DataOption[]
}

export default function Demo() {
const selectProps = useDataOptionsSelect({
queryOptions: {
queryKey: ['cities'],
queryFn: fetchCities,
},
filterable: true, // enables pinyin/text filtering
});

return <Select style={{ width: 200 }} {...selectProps} />;
}

useDataOptionsSelect Options

OptionTypeDefaultDescription
queryOptionsUseQueryOptions<TQueryFnData[], TData[], TParams>requiredTanStack Query options (queryKey, queryFn, and the rest of useQuery's options)
filterablebooleanfalseEnable client-side text/pinyin filtering
onFetch(data: TData[]) => voidCallback after data is fetched
labelKeystring | (item: TData) => string"label"Field mapping for the option label
valueKeystring | (item: TData) => Key"value"Field mapping for the option value
disabledKeystring | (item: TData) => boolean | undefined"disabled"Field mapping for the disabled state
descriptionKeystring | (item: TData) => string | undefined"description"Field mapping for the option description
childrenKeystring | (item: TData) => TData[] | undefined"children"Field mapping for nested option children (recursively transformed)

Each *Key option accepts either a string path (e.g. "user.name") or an extractor function.

The hook returns SelectProps that can be spread directly onto <Select>.

VEF Enhancement: useCodeSetOptionsSelect

For code-set-backed options, useCodeSetOptionsSelect wraps useCodeSetQuery and returns ready-to-spread SelectProps per alias:

import { Select, useCodeSetOptionsSelect } from '@vef-framework-react/components';

export default function Demo() {
const { gender, status } = useCodeSetOptionsSelect({
gender: 'common.gender',
status: { key: 'common.status', filterable: true },
});

return (
<>
<Select style={{ width: 200 }} {...gender} />
<Select style={{ width: 200 }} {...status} />
</>
);
}

All aliases are fetched in one batched code-set query. See Code Sets for the backing query and app-context wiring.

useCodeSetOptionsSelect Signature

function useCodeSetOptionsSelect<const T extends CodeSetAliasMap>(
keys: T,
options?: UseCodeSetOptionsSelectOptions
): UseCodeSetOptionsSelectResult<T>;

keys (CodeSetAliasMap, required) maps each alias to a CodeSetKeyValue — either a code set key string, or a CodeSetKeyConfig object:

FieldTypeDefaultDescription
keyCodeSetKeyrequiredThe code set key (typed via the Register augmentation, otherwise string)
filterablebooleanthe hook-level filterablePer-alias override for search filtering

options (UseCodeSetOptionsSelectOptions, optional):

OptionTypeDefaultDescription
filterablebooleanfalseWhether each select should enable search; aliases with their own filterable config win over this default

Result (UseCodeSetOptionsSelectResult<T> = Record<keyof T, SelectProps<Key, DataOptionWithPinyin<DataOption>>>) — one SelectProps object per alias, each carrying:

FieldValueDescription
optionsDataOptionWithPinyin<DataOption>[]The code set entries (including nested children), each enhanced with precomputed pinyin for label and description
loadingbooleantrue while the batched code-set query is fetching
fieldNames{ label, value, options: 'children', groupLabel: 'label' }Maps DataOption's shape onto the select
maxTagCount'responsive'Collapses excess tags in multiple mode
listHeight280Dropdown list height
notFoundContentLoader while fetchingShows a loader instead of "no data" during the initial fetch
showSearchbooleanThe resolved per-alias filterable flag
filterOption(input, option) => booleanMatches label / description, their full pinyin, and pinyin initials (only set when filterable)

API

PropTypeDefaultDescription
valuestring | string[]Selected value (controlled)
defaultValuestring | string[]Initial value (uncontrolled)
optionsSelectOption[]Option list
mode'multiple' | 'tags'Multi-select mode
placeholderstringPlaceholder text
disabledbooleanfalseDisable the select
loadingbooleanfalseShow loading state
showSearchbooleanfalseEnable search
allowClearbooleanfalseShow clear button
filterOptionboolean | functiontrueFilter function
size'large' | 'medium' | 'small''medium'Select size ('middle' is a deprecated alias for 'medium')
status'error' | 'warning'Validation status
variant'outlined' | 'filled' | 'borderless''outlined'Visual variant
onChange(value, option) => voidChange handler
onSearch(value: string) => voidSearch handler
onClear() => voidClear handler

Best Practices

  • Use useDataOptionsSelect for remote data to avoid manual loading state management.
  • Set allowClear for optional fields.
  • For form usage, use the Form field component, which integrates with the VEF form system:
<form.AppField name="city">
{(field) => <field.Select label="City" options={options} />}
</form.AppField>