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:

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

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

Arguments

Argument Type Required? Description
options Options true Required options object

Options

Option Type Required? Description
filter MultiListFilter true The MultiListFilter you would like to act on

Result

Property Type Description
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 () => void Clears all selected values

Example

Copy
Copied
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>
  ));
}
Copyright © Norce 2023. All right reserved.