Dropdown Field
Searchable dropdown with type-ahead suggestions from static or remote sources
The dropdown field provides type-ahead suggestions as users type. It supports static options, DataSource queries, and remote API endpoints.
Basic Usage
{
type: 'dropdown',
label: 'Product',
key: 'product',
order: 0,
options: [
{ label: 'iPhone 15', value: 'iphone-15' },
{ label: 'Samsung Galaxy S24', value: 'galaxy-s24' }
]
}Properties
Required
options- Can be:- Static string array:
string[] - Static array:
[{label: string, value: string}] - DataSource query:
{ query: string } - Remote API config:
IRemoteOptionsConfig
- Static string array:
Optional
acceptNewValueIfNoOptions(boolean) - Allow custom values when options unavailable (default:true)
Plus all common field properties.
Options Types
Static string options
{
type: 'dropdown',
label: 'City',
key: 'city',
order: 0,
options: [
'New York',
'Los Angeles',
'Chicago'
]
}Static object options
{
type: 'dropdown',
label: 'City',
key: 'city',
order: 0,
options: [
{ label: 'New York', value: 'ny' },
{ label: 'Los Angeles', value: 'la' },
{ label: 'Chicago', value: 'chi' }
]
}DataSource Query
{
type: 'dropdown',
label: 'Product',
key: 'product',
order: 0,
options: {
query: '.products | map({label:.name, value:.id})'
}
}Remote API
{
type: 'dropdown',
label: 'Company',
key: 'company',
order: 0,
options: {
url: '/api/companies/search',
method: 'GET',
queryParam: 'q',
labelField: 'name',
minQueryLength: 2,
debounceMs: 300
}
}Remote Options Configuration
When using remote options, the dropdown fetches data from your API as users type. This provides type-ahead functionality for large datasets.
Basic Remote Options
{
type: 'dropdown',
label: 'Customer',
key: 'customer',
order: 0,
options: {
url: '/api/customers/search',
labelField: 'name'
}
}Full Configuration
{
type: 'dropdown',
label: 'Customer',
key: 'customer',
order: 0,
options: {
// Required
url: '/api/customers/search', // API endpoint (absolute or relative)
// HTTP Configuration
method: 'POST', // 'GET' or 'POST' (default: 'GET')
queryParam: 'term', // Query parameter name (default: 'q')
requestHeaders: {
'X-Tenant': 'acme'
},
requestBodyTemplate: { // For POST requests only
includeArchived: false
},
// Response Configuration
responseOptionsPath: 'data.results', // Path to array in response (default: root)
labelField: 'fullName', // Field to use as label (default: 'label')
// Performance
minQueryLength: 2, // Min characters before fetching (default: 2)
debounceMs: 200, // Debounce delay in ms (default: 200)
cacheTtlMs: 300000, // Cache duration in ms (default: 300000 = 5 min)
negativeCacheTtlMs: 60000, // Error cache duration (default: 60000 = 1 min)
cacheMaxEntries: 300, // Max cache entries (default: 300)
maxOptions: 100, // Max options per response (default: 100)
// Advanced
normalizeQueryBeforeSent: 'lowercase', // 'default', 'lowercase', or 'uppercase'
timeoutMs: 10000, // Request timeout (default: 10000)
retry: 2, // Retry count for GET requests (default: 2)
headersAffectingKey: ['Accept-Language', 'X-Tenant'], // Headers for cache key
existenceConcurrency: 12 // Parallel validation requests (default: 12)
}
}Remote Options Properties
Required
url(string) - API endpoint to query for suggestions. Accepts absolute or relative URLs.
HTTP Configuration
method('GET' | 'POST') - HTTP method. For GET, query is sent via URL params. For POST, query is in the JSON body. Default:'GET'queryParam(string) - Name of the query parameter carrying the search term. For GET:?{queryParam}={term}. For POST:{ [queryParam]: term }. Default:'q'requestHeaders(object) - Headers included with every request. Include only headers that affect results (e.g.,Accept-Language,X-Tenant). Don't place secrets here in browser contexts.requestBodyTemplate(object) - Template object merged into POST request body. The query term is injected underqueryParam. Ignored for GET requests.
Response Configuration
responseOptionsPath(string) - Path to the array of items in the JSON response using JSON query language. Examples:'items'→response.items,'data.results'→response.data.results. The path is automatically prefixed with.if omitted. If invalid or doesn't resolve to an array, result is treated as empty.labelField(string) - Field name within each item to use as the label. If items are primitives (e.g.,string[]), the primitive value is used directly. Empty/whitespace-only labels are filtered out. Default:'label'
Performance Options
minQueryLength(number) - Minimum query length to trigger a remote fetch. Queries shorter than this return[]immediately. Default:2debounceMs(number) - Debounce interval in milliseconds for type-ahead. Default:200cacheTtlMs(number) - Time-to-live in milliseconds for positive cache entries. Within this window, identical queries are served from memory. Default:300000(5 minutes)negativeCacheTtlMs(number) - Time-to-live in milliseconds for negative cache entries (network/server errors). Prevents request storms on repeated failures. Not applied for AbortError. Default:60000(1 minute)cacheMaxEntries(number) - Maximum number of distinct cache keys kept in memory (LRU). Evicts least-recently-used entry when capacity is exceeded. Default:300maxOptions(number) - Maximum number of options extracted from a single response. Protects UI and memory if server returns large arrays. Default:100
Advanced Options
normalizeQueryBeforeSent('default' | 'lowercase' | 'uppercase') - Normalization policy applied to query before sending and when comparing labels. The normalized text participates in the cache key to avoid duplicate fetches. Default:'default'timeoutMs(number) - Request timeout in milliseconds. Default:10000retry(number) - Retry count for transient failures. Applies to GET requests only. Default:2headersAffectingKey(string[]) - Header names that affect the shape or contents of results and should be included in the cache key fingerprint (e.g.,'Accept-Language','X-Tenant'). Don't include authorization headers.existenceConcurrency(number) - Maximum number of parallel network requests used by the existence-checker. Higher values may increase throughput but can overwhelm network or server. Default:12
Use Cases
- Product search with large catalogs
- Customer/user lookup
- Location search (cities, addresses)
- Tag/category selection
- Any field with many options or remote data
Example
import type { IvtSchema } from '@ivandt/importer';
const schema: IvtSchema = {
title: 'Order Import',
publicKey: 'pk_live_xxx',
sessionToken: 'session_xxx',
fields: [
{
type: 'dropdown',
label: 'Customer',
key: 'customer',
order: 0,
options: {
url: '/api/customers/search',
method: 'GET',
labelField: 'name',
minQueryLength: 2
},
validators: [
{ type: 'required' }
]
},
{
type: 'dropdown',
label: 'Product',
key: 'product',
order: 1,
options: {
query: '.products | map({label:.name, value:.sku})'
}
}
]
};Remote API Features
- Debouncing: Prevents excessive API calls as user types
- Caching: Stores results in memory (LRU + TTL)
- Deduplication: Prevents duplicate requests for same query
- Concurrency Control: Limits parallel requests
- Error Handling: Graceful fallback on API failures
Accept New Values
{
type: 'dropdown',
label: 'Tag',
key: 'tag',
order: 0,
options: {
url: '/api/tags/search',
labelField: 'name'
},
acceptNewValueIfNoOptions: true // Allow custom values as options
}When true, users can enter values not in the options list.