Skip to content

Filter Group

KFilterGroup is a component that provides an interface for displaying and applying filter values.

Filters
html
<KFilterGroup
  v-model="selection"
  :filters="filters"
/>

Props

v-model

KFilterGroup uses v-model for data binding which tracks the filter selection state in a FilterGroupSelection. Each key in the selection state maps to a key in the filters prop.

ts
type FilterGroupSelection = Record<string, FilterSelection | undefined>

interface FilterSelection {
  operator: FilterOperator // 'eq' | 'neq' | 'contains' | 'exists' | 'lt' | 'lte' | 'gt' | 'gte'
  value: string | string[] // the user's selection
  text: string // the display string for that selection
}
Filters

html
<template>
  <KFilterGroup
    v-model="selection"
    :filters="filters"
  />
  <KButton
    :disabled="modelSelection?.status?.value === 'inprogress'"
    @click="filterInProgress"
  >
    Add "In Progress" filter
  </KButton>
  <KButton
    :disabled="selection?.name?.value === 'My name' && Object.keys(selection).length === 1"
    @click="resetModelSelection"
  >
    Reset
  </KButton>
</template>

<script setup lang="ts">
import type {
  FilterGroupFilters,
  FilterGroupSelection,
  FilterSelection,
} from '@kong/kongponents'

const defaultNameSelection: FilterSelection = {
  operator: 'eq',
  text: 'My name',
  value: 'My name',
}

const filters: FilterGroupFilters = {} // see `filters` below

const selection = ref<FilterGroupSelection>({
  name: defaultNameSelection,
})

const resetModelSelection = () => {
  selection.value.name = defaultNameSelection,
}

const filterInProgress = () => {
  selection.value = {
    ...selection.value,
    status: {
      operator: 'eq',
      value: 'inprogress',
      text: 'In Progress',
    }
  }
}

</script>

filters

Prop for passing list of available filters. Accepts object of type FilterGroupFilters. See filter examples for each possible filter that can be used. Each filter must provide a label, all other properties are optional. Each key in the filters prop maps to a key in the v-model object.

ts
export type FilterGroupFilters = Record<string, Filter>
export interface Filter {
  label: string
  operators?: FilterOperator[]
  options?: FilterOption[]
  multiple?: boolean
  pinned?: boolean
  placement?: PopPlacement
  maxWidth?: number | string
}

filter.label

Displayed in the filter selection dropdown, the filter pill, and the popover with the filter's content.

filter.operators

One or more of eq, neq, contains, exists, lt, lte, gt, gte. Renders an operator selection for the end user when more than one is provided. See operator usage.

OperatorDisplayed in dropdownDisplayed in pill
eqEquals[label] = [value]
neqNot equals[label] ≠ [value]
containsContains[label]: [value]
existsExists[label]: [value]
ltLess than[label] < [value]
lteLess than or equal to[label] ≤ [value]
gtGreater than[label] > [value]
gteGreater than or equal to[label] ≥ [value]

filter.options

An array of { label: …, value: … } items. Used in select filters and multiselect filters.

filter.multiple

If options are set, this determines whether or not those options will be rendered as a select filter or a multiselect filter

filter.pinned

If true the filter will always be rendered as a pill regardless of whether it has a value or not and will never appear in the "Add filter" dropdown as it's always visible. If false, will only be rendered as a pill when it has a current value.

filter.placement

Where the filter's popover will be placed, defaults to bottom-start. See popover placement

filter.maxWidth

The max width of the filter's popover, defaults to 400px. See popover maxWidth

selectorLabel

Sets the text content in the filter selector. Defaults to 'Add filter'.

Filters
html
<KFilterGroup
  v-model="selection"
  :filters="filters"
  selector-label="Custom filter selector"
/>

groupLabel

The label to display at the beginning of the group. If set to an empty string nothing will be displayed. Defaults to 'Filters'.

html
<KFilterGroup
  v-model="selection"
  :filters="filters"
  group-label=""
/>

Slots

Filter Content

Custom content can be slotted into each filter. The corresponding filter key from the filters prop should be used to target the appropriate filter-* slot. When custom content is provided, KFilterGroup is no longer able to determine the user's selection for that filter, therefore the selection.* for that filter must be managed by the host app.

Filters
html
<template>
  <KFilterGroup
    v-model="selection"
    :filters="filters"
    @apply="onApply"
    @clear="onClear"
    @open="onOpen"
  >
    <template #filter-customNodes>
      <KSlider
        v-model="customNodes"
        label="Value"
        show-marks
        :show-value="false"
      />
    </template>
  </KFilterGroup>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { FilterGroupFilters, FilterGroupSelection, FilterSelection } from '@kong/kongponents'

const selection = ref<FilterGroupSelection>({})

const filters: FilterGroupFilters = {
  customNodes: {
    label: 'Minimum nodes',
    operators: ['eq'],
    pinned: true,
  },
}

const customNodes = ref<number>(0)

const onApply = (key: string) => {
  if (key === 'customNodes') {
    selection.value.customNodes = {
      operator: 'eq',
      value: customNodes.value.toString(),
      text: customNodes.value.toString(),
    }
  }
}

const onClear = (key: string) => {
  if (key === 'customNodes') {
    delete selection.value.customNodes
  }
}

const onOpen = (key: string) => {
  if (key === 'customNodes') {
    const currentValue = Number.parseInt(customNodesSelection.value?.customNodes?.value)
    customNodes.value = Number.isNaN(currentValue) ? 0 : currentValue
  }
}
</script>

Events

apply

Emitted when the apply button is clicked. Event payload is the applied filter's key and the value of the entire KFilterGroup's selection (described in v-model).

clear

Emitted when the X icon is clicked in the filter pill. Event payload is the cleared filter's key and the value of the entire KFilterGroup's selection (described in v-model).

close

Emitted when the filter's popover content is closed (including when selection is applied). Event payload is the closed filter's key.

open

Emitted when the filter's popover content is opened. Event payload is the opened filter's key.

Filter Examples

KFilterGroup supports four filter types, determined by the filter configuration:

Select Filter

A select filter is rendered when options is provided and multiple is false or undefined.

Filters
html
<KFilterGroup
  v-model="selection"
  :filters="{
    status: {
      label: 'Status',
      options: [
        { value: 'todo', label: 'Todo' },
        { value: 'inprogress', label: 'In Progress' },
        { value: 'done', label: 'Done' },
      ],
      pinned: true,
    },
  }"
/>

Multiselect Filter

A multiselect filter is rendered when multiple is true and options is provided.

Filters
html
<KFilterGroup
  v-model="selection"
  :filters="{
    tag: {
      label: 'Tag',
      operators: ['contains'],
      multiple: true,
      options: [
        { value: 'foo', label: 'Foo' },
        { value: 'bar', label: 'Bar' },
        { value: 'baz', label: 'Baz' },
        { value: 'bat', label: 'Bat' },
      ],
      pinned: true,
    },
  }"
/>

Text Filter

A text filter is rendered when options is not provided.

Filters
html
<KFilterGroup
  v-model="selection"
  :filters="{
    Name: {
      label: 'Name',
      pinned: true,
    },
  }"
/>

Custom Filter

A custom filter is rendered when content is provided in the filter-* slot.

Filters
html
<KFilterGroup
  v-model="selection"
  :filters="{
    created: {
      label: 'Created',
      pinned: true,
    },
  }"
>
  <template #filter-created>
    <MyCustomContent />
  </template>
</KFilterGroup>

Operator Usage

For any filter other than a Custom Filter, when more than one operator is set for a filter, an operator selection is rendered in the popover.

Filters
html
<KFilterGroup
  v-model="selection"
  :filters="{
    created: {
      label: 'Created',
      operators: ['eq', 'neq', 'contains', 'exists', 'lt', 'lte', 'gt', 'gte'],
      pinned: true,
    },
  }"
>
  <template #filter-created>
    <MyCustomContent />
  </template>
</KFilterGroup>

Released under the Apache-2.0 License.