Last updated

Multi List Filters

Multi List filters are comprised of one or more list filters, where the options in each list depends on the previous selection.

An example use case for this kind of filter is for filtering a list of cars. The Multi List Filter may have 3 lists in this case - make, model, and year. When the user selects a make, the models will become selectable, and will be based on the selected make. When a model is selected, the years become available.

Unlike List Filters, only one item in each list is selectable. So, in the above example, only one make, one model, and one year can be selected.

A query for multi list filters looks like this:

... on MultiListFilter {
  id
  name
  isActive @client
  lists {
    id
    hasActiveItems @client
    name
    items {
      id
      value
      text
      resultCount
      isActive @client
    }
  }
}

Notice the @client directives. When rendering the multi list filter these help you to indicate whether the multi list filter itself is active, which lists have active items, and which item in that list are selected.

useMultiFilter

The useMultiFilter hook can be used to update multi list filters. It will update the state of the 3 client fields in the query above, and will also update the URL params with the selected values.

const { apply, clearList, clearFilter } = useMultiFilter({ filter })

Arguments

ArgumentTypeRequired?Description
optionsOptionstrueRequired options object

Options

OptionTypeRequired?Description
filterMultiListFiltertrueThe MultiListFilter you would like to act on

Result

PropertyTypeDescription
apply({ value, listIndex }: { value: string, listIndex: number }) => Promise<ExecutionResult<MultiListFilter>>Applies the given value to the list specified by listIndex. Returns a promise that will resolve with the multi list filter.
clearList({ listIndex }: { listIndex: number }) => Promise<ExecutionResult<MultiListFilter>>Clears the selected value for the list specified by listIndex. Any lists with higher indexes will also be cleared.
clearFilter() => voidClears all selected values

Example

function MultiListFilter({ multiListFilter }) {
  const { apply, clearList } = useMultiFilter({
    filter: multiListFilter
  });

  // A multiListFilter has one or more `lists`.

  return multiListFilter.lists.map((list, index) => (
    <FilterDropdownMenu>
      <Button disabled={list.items.length === 0}>
        <span>{list.name}</span>
        {list.hasActiveItems ? <Check /> : <Carot className="carot" />}
      </Button>
      <Items as="ul">
        {list.items.map(item => (
          <DropdownMenuItem
            key={item.id}
            onSelect={({ setIsOpen }) => {
              apply({
                value: item.value,
                listIndex: index
              });
              setIsOpen(false);
            }}
          >
            <span>{item.text}</span>
            {item.isActive ? <Check /> : <span>{item.resultCount}</span>}
          </DropdownMenuItem>
        ))}
        <>
          {list.hasActiveItems && (
            <DropdownMenuItem
              onSelect={({ setIsOpen }) => {
                setIsOpen(false);
                clearList({ listIndex: index });
              }}
            >
              {t('Clear filter')}
            </DropdownMenuItem>
          )}
        </>
      </Items>
    </FilterDropdownMenu>
  ));
}