Description
The Autocomplete component is a combination of an Input and a Dropdown, also called ComboBox. During typing, matching data items gets suggested in an option menu (listbox).
Typeahead and ComboBox
The Autocomplete component may also be known as Typeahead or ComboBox. But autocomplete describes the purpose more precisely and descriptive, therefore Eufemia is using this term.
When to use it:
Use it for both small autocomplete purposes and large (async) data set searches. The component supports two ways of showing ProgressIndicator.
You may check out the Dropdown component for more details on how to use it etc. They both share the same DrawerList.
Highlighting
Words found during typing are highlighted. The rules are:
- The two first words will match the beginning of a word
- The third word will match inside a word (can be changed with
search_in_word_index
) - Case insensitive
Using Components inside content
It is not possible to wrap them inside React Components. The reason is that the Autocomplete component needs to know what data it wants to search for before your React Component has rendered. But also, the component can't update the HTML to make the bold highlighting – "after" your component has rendered.
That means you can't run a component that will render as soon as it is displayed.
If you need to format numbers, then do it before you send in the data content.
It is possible to wrap your content inside one HTML Element. Nested elements are not supported.
To wrap your content only visually, you can provide your wrappers inside an array:
<Autocompletedata={[{content: [<IconPrimary icon="bell" key="item-1" />,<span className="custom-selector-a" key="item-2">The Shawshank Redemption</span>,<span className="custom-selector-b" key="item-3">The Dark Knight</span>,// etc.<NumberFormat value={1234} key="item-4" />, // <-- Not searchable nor highlightable],},]}label="Label:"/>
or you can provide it inside a fragment:
<Autocompletedata={[{content: (<><IconPrimary icon="bell" /><span className="custom-selector-a">The Shawshank Redemption</span><span className="custom-selector-b">The Dark Knight</span></>),},]}label="Label:"/>
and if you need to decouple the searchable content from what's displayed, then you can put your searchable content inside search_content
:
<Autocompletedata={[{content: ['your visual content'],search_content: ['your search content'],},]}label="Label:"/>
Numbers
Numbers are often different than a word filter. You can use search_numbers={true}
to enable a number specialized filtering. See example in the demos.
Now the user could search for e.g. bank account numbers by just entering 201
, even if you format it like 2000 12 34567
(e.g. use format(20001234567, { ban: true }) from /components/number-format/NumberUtils)
Screen reader support
To enhance screen-reader usage, this component uses aria-live
to announce the number of options found (aria_live_options
).
Custom size
.dnb-autocomplete {--autocomplete-width: 20rem; /* custom width */}
You can also set the width directly, but then it has to be defined like so (including min-width
):
/** Because of the included label/status etc. we target the "__shell" */.dnb-autocomplete__shell {width: 10rem;}/** In order to change only the drawer-list width */.dnb-autocomplete .dnb-drawer-list__root {width: 10rem;}
Dynamically change data
You can manipulate the used data dynamically, either by changing the data
property or during user events like on_type
or on_focus
. The following properties and methods are there to use:
Methods
updateData
replace all data entries.emptyData
remove all data entries.setInputValue
update the input value.showIndicator
shows a progress indicator instead of the icon (inside the input).hideIndicator
hides the progress indicator inside the input.showIndicatorItem
shows an item with a ProgressIndicator status as an data option item.showNoOptionsItem
shows the "no entries found" status as an data option item.setVisible
shows the DrawerList.setHidden
hides the DrawerList.showAllItems
shows all DrawerList items.setMode
switch the mode during runtime.debounce
a debounce method with a cancel invocation method on repeating calls. There is more documentation about this method.
Properties
dataList
contains all the data entries.
Example
<Autocompleteon_focus={({ updateData, showIndicator }) => {showIndicator()setTimeout(() => {updateData(topMovies)}, 1e3)}}on_type={({ value /* updateData, ... */ }) => {console.log('on_type', value)}}/>
Demos
Default autocomplete
<Autocomplete data={topMovies} label="Label:" />
Autocomplete with numbers
<Autocompleteinput_value="201"show_clear_buttonlabel="Label:"data={[format(20001234567, {ban: true,}),format(22233344425, {ban: true,}),format(1234.5, {currency: true,}),format('+47116000', {phone: true,}),]}search_numbers={true}/>
Autocomplete with a custom title
keep_value
means the input value gets not removed after an input blur happens.show_clear_button
means a clear button will show up when the input field contains a value.
<Autocompletedata={topMovies}keep_value={true}show_clear_button={true}label="Label:"placeholder="Custom placeholder ..."on_change={({ data }) => {console.log('on_change', 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 disable_filter
if you have a backend doing the search operation.
const onTypeHandler = ({value,showIndicator,hideIndicator,updateData,debounce,/* ... */}) => {console.log('typed value:', value)showIndicator()debounce(({ value }) => {console.log('debounced value:', value)// simulate server delayconst timeout = setTimeout(() => {// update the drawerListupdateData(topMovies)hideIndicator()}, 600)// cancel invocation methodreturn () => clearTimeout(timeout)},{value,},250)}render(<Autocompletemode="async"on_type={onTypeHandler}no_scroll_animation={true}placeholder="Search ..."/>)
Update data dynamically on the first focus
const onFocusHandler = ({ updateData, dataList, showIndicatorItem }) => {if (!dataList.length) {showIndicatorItem()setTimeout(() => {updateData(topMovies)}, 1e3)}}render(<Autocompletemode="async"no_scroll_animation={true}prevent_selection={true}on_type={({ value /* updateData, ... */ }) => {console.log('on_type', value)}}on_focus={onFocusHandler}/>)
With a Button to toggle the open / close state
NB: Just to show the possibility; the data is given as a function.
<Autocompletelabel="Label:"value={10}show_submit_button={true}on_change={({ data }) => {console.log('on_change', data)}}>{() => topMovies}</Autocomplete>
With a predefined input/search value
<Autocompletelabel="Label:"input_value="the pa ther"no_animationon_change={({ data }) => {console.log('on_change', data)}}>{() => topMovies}</Autocomplete>
Different sizes
Four sizes are available: small
, default
, medium
and large
.
<FormRow direction="vertical"><Autocompletelabel="Label:"size="default"bottomdata={() => topMovies}/><Autocompletelabel="Label:"size="medium"bottomdata={() => topMovies}/><Autocompletelabel="Label:"size="large"bottomdata={() => topMovies}/></FormRow>
Data suffix value
Data is provided as such:
const { locale } = React.useContext(Context)const data = [{suffix_value: (<NumberFormat currency srLabel="Total:" locale={locale}>{12345678}</NumberFormat>),selected_value: `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(<CustomWidthvalue={1}data={numbers}size="medium"input_icon={null}show_submit_buttonlabel="From account"label_direction="vertical"/>)
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(<FormRow direction="vertical"><CustomWidthOnelabel="Label:"label_sr_onlysize="default"icon_position="left"bottomdata={topMovies}/><CustomWidthTwolabel="Label:"label_sr_onlysize="medium"bottomdata={topMovies}/><CustomWidthThreelabel="Label:"label_sr_onlysize="large"align_autocomplete="right"icon_position="right"input_icon="bell"bottomdata={topMovies}/></FormRow>)
Autocomplete with status message
<Autocompletedata={topMovies}label="Label:"status="Please select a valid date"status_state="info"show_submit_button/>