AutocompleteInput
The AutocompleteInput module provides you input components that include a
dropdown for autocomplete suggestions. There are two components exported from
the module, one for a single-selection field and another for multi-selection.
Usage
The components are controlled components. That means that you are responsible to tell the components which items are currently selected and which are visible in the dropdown.
An item in terms of this component is an object that contains at least two
properties: An id property that is unique among all the items that are
selected or visible and a label property, which will be shown when the item
is displayed.
You are of course allowed to pass objects as items that contain more than the required properties. If you use TypeScript, you can pass the type definition of your items as generic argument to the component:
const props = {/* Define your props */};
type CustomItem = { id: string; label: string; foo: number };
const Foo = () =>
<AutocompleteInput.SingleSelect<CustomItem> {...props} />;
Both single- and multi-select have a set of common props, which are defined in the following table:
| Property name | Type | Required | Values | Default |
|---|---|---|---|---|
renderItem | RenderItem | ✅ | - | - |
visibleItems | VisibleItemsGetter | ✅ | - | - |
onInputValueChange | InputValueChangeHandler | - | - | |
id | string | - | - | |
name | string | - | - | |
placeholder | string | - | - | |
state | string | see the states of the InputBox component | - |
Here are the complete type definitions:
type RenderItem = (item: Item) => React.ReactNode;
type VisibleItemsGetter = (
downshift: ControllerStateAndHelpers<Item>,
) => Item[];
type InputValueChangeHandler = (
inputValue: string,
downshift: ControllerStateAndHelpers<Item>,
) => void;
The ControllerStateAndHelpers is taken from downshift. Item is the type
of the items used when rendering the component.
The props id, name, state and placeholder will be passed to the
InputBox which is used under the hood to render the styled
input field.
To control the items shown in the dropdown below the input field you have to
pass a function via the visibleItems prop. To allow you to base the visible
items on the current state of the component, we pass all the internal
downshift-state as argument to this function. You can for example use the
current value of the input element like this:
<AutocompleteInput.SingleSelect
visibleItems={(downshift) => {
const currentInput = downshift.inputValue;
// Decide on which items to show...
}}
{...otherProps}
/>
To actually render the individual items you have to pass a renderItem prop.
This function will be called for each individual item. You have to return a
ReactNode that will be inserted in the list of visible item.
To listen on change events for the input field you can pass a handler via the
onInputValueChange prop. This function will be called with the new value of
the input as first argument and with the current downshift state as the
second argument. (Note that the event handler is called before the
downshift state is update. That means downshift.inputValue still contains
the old value of the input element.)
Single-select
The following props are specific to the single-select component:
| Property name | Type | Required | Values | Default | |
|---|---|---|---|---|---|
onSelect | SelectHandler | ✅ | - | - | |
selectedItem | `Item | null` | ✅ | - | - |
clearInputValueOnSelection | boolean | - | - |
Here is the complete type definition for the onSelect prop:
type SelectHandler = (
selectedItem: Item | null,
downshift: ControllerStateAndHelpers<Item>,
) => void;
Multi-select
The following props are specific to the single-select component:
| Property name | Type | Required | Values | Default |
|---|---|---|---|---|
onSelectionChange | SelectHandler | ✅ | - | - |
selectedItems | Item[] | ✅ | - | - |
Here is the complete type definition for the onSelectionChange prop:
type SelectHandler = (
selectedItems: Item[],
downshift: ControllerStateAndHelpers<Item>,
) => void;
Example
Single-select
type Item = { id: string; label: string };
const items = [
{ id: "apple", label: "Apple" },
{ id: "banana", label: "Banana" },
{ id: "coconut", label: "Coconut" },
];
const SingleSelectExample: React.FC = () => {
const [selectedItem, setSelectedItem] = useState<Item | null>(null);
return (
<Spacings.Stack>
<label htmlFor="single-select">
<Text>Select a fruit</Text>
</label>
<AutocompleteInput.SingleSelect
clearInputValueOnSelection
id="single-select"
onSelect={(item) => {
setSelectedItem(item);
}}
selectedItem={selectedItem}
visibleItems={(downshift) =>
downshift.inputValue === ""
? items
: items.filter((item) =>
item.label
.toLowerCase()
.includes((downshift.inputValue || "").toLowerCase()),
)
}
/>
</Spacings.Stack>
);
};
Multi-select
type Item = { id: string; label: string };
const items = [
{ id: "apple", label: "Apple" },
{ id: "banana", label: "Banana" },
{ id: "coconut", label: "Coconut" },
];
const MultiSelectExample: React.FC = () => {
const [selectedItems, setSelectedItems] = useState<Item[]>([]);
return (
<Spacings.Stack>
<label htmlFor="multi-select">
<Text>Select multiple fruits</Text>
</label>
<AutocompleteInput.MultiSelect
id="multi-select"
onSelectionChange={(itemList) => {
setSelectedItems(itemList);
}}
selectedItems={selectedItems}
visibleItems={(downshift) =>
downshift.inputValue === ""
? items
: items.filter((item) =>
item.label
.toLowerCase()
.includes((downshift.inputValue || "").toLowerCase()),
)
}
/>
</Spacings.Stack>
);
};