AddressSearch

The AddressSearch module provides you an input component that includes a dropdown for autocomplete suggestions.

Usage

The component is controlled. That means that you are responsible to tell it which item is 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 = () => <AddressSearch<CustomItem> {...props} />;

The accepted props are defined in the following table:

Property nameTypeRequiredValuesDefault
visibleItemsItem[]--
onInputValueChangeInputValueChangeHandler--
onSelectSelectHandler--
selectedItemItem--
idstring--
namestring--
placeholderstring--
isLoadingboolean--
labelIdstring--
usePxUnitsboolean--

Here are the complete type definitions:

type InputValueChangeHandler = (inputValue: string) => void;
type SelectHandler = (selectedItem: Item | null) => void;

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 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.

To control the items shown in the dropdown below the input field you have to pass the visibleItems prop. You can update the visible items based on the current input value like this:

const [filteredItems, setFilteredItems] = useState<Item>(initialItems);
<AddressSearch
  onInputValueChange={(newValue) => {
    // Filter the values based on the new value.
    setFilteredItems(initialItems.filter((item) => item.includes(newValue)));
    // You can also use a debounce for server-side filtering.
  }}
  visibleItems={filteredItems}
  {...otherProps}
/>;

Example

type Item = { id: string; label: string };
const items = [
  { id: "munich", label: "München" },
  { id: "london", label: "London" },
  { id: "sf", label: "San Francisco" },
];
const AddressSearchExample: React.FC = () => {
  const [selectedItem, setSelectedItem] = useState<Item | null>(null);
  const [filteredValues, setFilteredValues] = useState<Item[]>(items);
  return (
    <Spacings.Stack>
      <label htmlFor="address-search">
        <Text>Select an address</Text>
      </label>
      <AddressSearch
        id="address-search"
        onSelect={(item) => {
          setSelectedItem(item);
        }}
        onInputValueChange={(newValue) => {
          setFilteredValues(
            items.filter((item) =>
              item.label.toLowerCase().includes(newValue.toLowerCase()),
            ),
          );
        }}
        selectedItem={selectedItem}
        visibleItems={filteredValues}
      />
    </Spacings.Stack>
  );
};