Demos
Default autocomplete
<Autocomplete data={topMovies} label="Label" />
Autocomplete with numbers
<Autocomplete inputValue="201" showClearButton label="Label" data={numbersData} searchNumbers={true} />
Autocomplete with a custom title
keepValuemeans the input value gets not removed after an input blur happens.showClearButtonmeans a clear button will show up when the input field contains a value.
<Autocomplete data={topMovies} keepValue={true} showClearButton={true} label="Label" placeholder="Custom placeholder ..." onChange={({ data }) => { console.log('onChange', data) }} />
Async usage, dynamically update data during typing
This example simulates server delay with a timeout and - if it gets debounced, we cancel the timeout. Read more about the debounce method.
Also, you may consider using disableFilter if you have a backend doing the search operation.
const onTypeHandler = ({ value, showIndicator, hideIndicator, updateData, showNoOptionsItem, debounce, /* ... */ }) => { console.log('typed value:', value) showIndicator() debounce( ({ value }) => { console.log('debounced value:', value) const normalizedValue = value.trim().toLowerCase() const filteredData = topMovies.filter(({ content }) => { if (typeof content === 'string') { return content.toLowerCase().includes(normalizedValue) } if (Array.isArray(content)) { return content .filter((part) => typeof part === 'string') .join(' ') .toLowerCase() .includes(normalizedValue) } return false }) const newData = normalizedValue.length > 0 ? filteredData : topMovies // simulate server delay const timeout = setTimeout(() => { // update the drawerList updateData(newData) hideIndicator() if (newData.length === 0) { showNoOptionsItem() } }, 600) // cancel invocation method return () => clearTimeout(timeout) }, { value, }, 250 ) } render( <Autocomplete mode="async" onType={onTypeHandler} noScrollAnimation={true} placeholder="Search ..." /> )
Update data dynamically on the first focus
const onFocusHandler = ({ updateData, dataList, showIndicatorItem }) => { if (!dataList.length) { showIndicatorItem() setTimeout(() => { updateData(topMovies) }, 1e3) } } render( <Autocomplete mode="async" noScrollAnimation={true} preventSelection={true} onType={({ value /* updateData, ... */ }) => { console.log('onType', value) }} onFocus={onFocusHandler} /> )
With a Button to toggle the open / close state
NB: Just to show the possibility; the data is given as a function.
<Autocomplete label="Label" value={10} showSubmitButton={true} onChange={({ data }) => { console.log('onChange', data) }} > {() => topMovies} </Autocomplete>
With a predefined input/search value
<Autocomplete label="Label" inputValue="the pa ther" noAnimation onChange={({ data }) => { console.log('onChange', data) }} > {() => topMovies} </Autocomplete>
Inline results
Use the inline property to render the results list persistently open in normal document flow, instead of as an overlay. The toggle button is hidden, while filtering, highlighting, selection and keyboard navigation stay the same.
<Autocomplete inline stretch label="Label" data={topMovies} />
Different sizes
Four sizes are available: small, default, medium and large.
<Flex.Vertical> <Autocomplete label="Label" size="default" data={() => topMovies} /> <Autocomplete label="Label" size="medium" data={() => topMovies} /> <Autocomplete label="Label" size="large" data={() => topMovies} /> </Flex.Vertical>
Data suffix value
Data is provided as such:
const { locale } = React.useContext(Context)const data = [{suffixValue: (<NumberFormat.Currency srLabel="Total:" locale={locale}>{12345678}</NumberFormat.Currency>),selectedValue: `Brukskonto (${ban})`,content: ['Brukskonto', ban],},]
const CustomWidth = styled(Autocomplete)` .dnb-drawer-list__root, .dnb-autocomplete__shell { width: 50vw; min-width: 15rem; max-width: 30rem; } ` render( <CustomWidth value={1} data={numbers} size="medium" icon={null} showSubmitButton label="From account" /> )
Custom width
const CustomWidthOne = styled(Autocomplete)` .dnb-autocomplete__shell { width: 10rem; } ` const CustomWidthTwo = styled(Autocomplete)` &.dnb-autocomplete--is-popup .dnb-drawer-list__root { width: 12rem; } ` const CustomWidthThree = styled(Autocomplete)` /** Change the "__shell" width */ .dnb-autocomplete__shell { width: 12rem; } /** Change the "__list" width */ .dnb-drawer-list__root { width: 20rem; } ` render( <Flex.Vertical> <CustomWidthOne label="Label" labelSrOnly size="default" iconPosition="left" data={topMovies} /> <CustomWidthTwo label="Label" labelSrOnly size="medium" data={topMovies} /> <CustomWidthThree label="Label" labelSrOnly size="large" align="right" iconPosition="right" icon="bell" data={topMovies} /> </Flex.Vertical> )
Autocomplete with status message
<Autocomplete data={topMovies} label="Label" status="You need to select a movie" statusState="information" showSubmitButton />
Autocomplete with List item content
Reuse the List row layout for rich option content. The option is already an <li> and wraps its content in <span> elements, so use element="span" on List.Item.Basic and its cells to keep the markup valid. Give the Autocomplete a width that fits both the title and the end value. Provide selectedValue with the plain text so the input shows a sensible value once an option is selected, and searchContent so typing still filters the options. See rendering a row outside a List.Container for the details.
// A List row keeps its end cell at content width, so the row needs // horizontal room. Give the Autocomplete a width of its own, or the // title column will be squeezed by the end cell. const AccountAutocomplete = styled(Autocomplete)` .dnb-autocomplete__shell, .dnb-drawer-list__root { width: 22rem; } ` const data = [ { selectedKey: 'accounts', // selectedValue is the plain text shown in the input once selected; // searchContent keeps typing/filtering working with rich content selectedValue: 'Accounts', searchContent: 'Accounts Bills Savings', content: ( <List.Item.Basic element="span"> <List.Cell.Title element="span">Accounts</List.Cell.Title> <List.Cell.End element="span">Bills, Savings</List.Cell.End> </List.Item.Basic> ), }, { selectedKey: 'loans', selectedValue: 'Loans', searchContent: 'Loans Mortgage Car', content: ( <List.Item.Basic element="span"> <List.Cell.Title element="span">Loans</List.Cell.Title> <List.Cell.End element="span">Mortgage, Car</List.Cell.End> </List.Item.Basic> ), }, { selectedKey: 'cards', selectedValue: 'Cards', searchContent: 'Cards Visa Mastercard', content: ( <List.Item.Basic element="span"> <List.Cell.Title element="span">Cards</List.Cell.Title> <List.Cell.End element="span">Visa, Mastercard</List.Cell.End> </List.Item.Basic> ), }, ] render(<AccountAutocomplete data={data} label="Label" />)
Groups
If an item has a groupIndex property, it will use the groups in the groups property. Only the first group can be without title, all other groups must have a title.
<Autocomplete groups={[undefined, 'Pets', 'Cars']} data={[ { groupIndex: 0, content: 'Default 1', }, { groupIndex: 0, content: 'Default 2', }, { groupIndex: 1, content: 'Cat', }, { groupIndex: 1, content: 'Dog', }, { groupIndex: 2, content: 'Jeep', }, { groupIndex: 2, content: 'Van', }, ]} />
No divider
We can remove the divider between items with the noDivider prop. Beware that this can make information dense lists difficult to parse.
<Autocomplete noDivider data={['Cat', 'Dog', 'Canary', 'Hamster', 'Piglet']} />