Multi-condition filter (AND / OR)

Two conditions on ONE column, joined by AND or OR: a salary band (> 80k AND < 150k), age outliers (< 25 OR > 60). Open the funnel and click "+ Add condition", or drive it via api.setFilter({ operator, value, operator2, value2, join }).

A live, editable Svelte 5 data grid example from the SvGrid gallery (Filtering & Search). See the SvGrid documentation for the full API.

About this example

Two conditions on one column in the Svelte 5 data grid, joined by AND or OR: a salary band of more than 80k and less than 150k, or age outliers under 25 or over 60. Open a column's funnel menu and click Add condition, or set it from code with api.setFilter(col, { operator, value, operator2, value2, join }); preset buttons apply each example and api.clearAllFilters resets.

A single column can hold TWO conditions joined by AND or OR - a numeric band ("> 80k AND < 150k"), an either/or text match, an outlier filter ("< 25 OR > 60"). Open a column's funnel menu and click "+ Add condition", or drive it from the API with setFilter(col, { operator, value, operator2, value2, join }). The preset buttons below do exactly that.

Imports, features and API used

Imports: @svgrid/grid, ../shared/seed

Table features registered: rowSortingFeature, columnFilteringFeature

Columns: firstName (First name), lastName (Last name), department (Department), age (Age), salary (Salary)

SvGridApi methods called: api.clearAllFilters(), api.setFilter()

Frequently asked questions

How do I add a second condition to a column filter?

In the column menu click Add condition, choose the join (AND or OR) and fill the second operator and value. Both conditions show in the menu and the funnel icon marks the column as filtered.

What does the API call look like?

api.setFilter('salary', { operator: 'greaterThan', value: '80000', operator2: 'lessThan', value2: '150000', join: 'AND' }). Omit operator2 for a single condition; join is AND or OR.

Can I combine this with the inline filter row?

Yes. showColumnFilters keeps the filter row visible under the headers while the menu holds the compound editor; both write the same column filter state.

Related documentation

Related articles

Source code (178-multi-condition-filter.svelte)

<!-- Documented in: docs/help/filtering/filter-conditions.md -->
<script lang="ts">
  /**
   * 178. Multi-condition filter (AND / OR within one column)
   * --------------------------------------------------------
   * A single column can hold TWO conditions joined by AND or OR - a numeric
   * band ("> 80k AND < 150k"), an either/or text match, an outlier filter
   * ("< 25 OR > 60"). Open a column's funnel menu and click "+ Add condition",
   * or drive it from the API with `setFilter(col, { operator, value,
   * operator2, value2, join })`. The preset buttons below do exactly that.
   */
  import {
    SvGrid,
    tableFeatures,
    rowSortingFeature,
    columnFilteringFeature,
    type GridColumns,
    type SvGridApi,
  } from '@svgrid/grid'
  import { makePeople, type Person } from '../shared/seed'

  const features = tableFeatures({ rowSortingFeature, columnFilteringFeature })
  let rows = $state<Person[]>(makePeople(120))
  let api = $state<SvGridApi<typeof features, Person> | null>(null)
  let activePreset = $state<string>('band')

  const columns: GridColumns<Person> = [
    { field: 'firstName', header: 'First name', width: 130 },
    { field: 'lastName', header: 'Last name', width: 130 },
    { field: 'department', header: 'Department', width: 150 },
    { field: 'age', header: 'Age', editorType: 'number', width: 100, align: 'right' },
    { field: 'salary', header: 'Salary', editorType: 'number', width: 150, align: 'right',
      format: { type: 'currency', currency: 'USD', options: { maximumFractionDigits: 0 } } },
  ]

  function salaryBand() {
    activePreset = 'band'
    api?.clearAllFilters()
    // salary > 80,000 AND salary < 150,000  (a band)
    api?.setFilter('salary', {
      operator: 'greaterThan', value: '80000',
      operator2: 'lessThan', value2: '150000', join: 'AND',
    })
  }
  function ageOutliers() {
    activePreset = 'outliers'
    api?.clearAllFilters()
    // age < 25 OR age > 60  (the two tails)
    api?.setFilter('age', {
      operator: 'lessThan', value: '25',
      operator2: 'greaterThan', value2: '60', join: 'OR',
    })
  }
  function clearAll() {
    activePreset = 'none'
    api?.clearAllFilters()
  }
</script>

<section class="flex flex-col flex-1 min-h-0 gap-3">
  <div class="flex flex-wrap items-center gap-2 shrink-0">
    <button type="button" class="mc-btn" class:is-on={activePreset === 'band'} onclick={salaryBand}>
      Salary 80k &lt; x &lt; 150k <span class="mc-join">AND</span>
    </button>
    <button type="button" class="mc-btn" class:is-on={activePreset === 'outliers'} onclick={ageOutliers}>
      Age &lt; 25 or &gt; 60 <span class="mc-join mc-or">OR</span>
    </button>
    <button type="button" class="mc-btn" class:is-on={activePreset === 'none'} onclick={clearAll}>Clear</button>
    <span class="text-xs" style="color: var(--sg-muted);">
      …or open any column's <strong>funnel menu</strong> and click <em>+ Add condition</em>.
    </span>
  </div>

  <p class="text-sm shrink-0" style="color: var(--sg-fg);">
    Two conditions per column, joined by <code>AND</code> / <code>OR</code>.
    Set via <code>api.setFilter(col, {'{'} operator, value, operator2, value2, join {'}'})</code>
    or the column menu.
  </p>

  <div class="flex-1 min-h-0">
    <SvGrid responsive={true}
      columnResize
      data={rows}
      columns={columns}
      features={features}
      filterMode="menu"
      showColumnFilters={true}
      showRowNumbers={true}
      rowHeight={36}
      containerHeight="100%"
      fitColumns={true}
      onApiReady={(next) => { api = next; salaryBand() }}
    />
  </div>
</section>

<style>
  .mc-btn {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 6px 12px; border-radius: 7px;
    font-size: 12.5px; font-weight: 600;
    color: var(--sg-fg); background: var(--sg-header-bg);
    border: 1px solid var(--sg-border); cursor: pointer;
    transition: border-color 120ms ease, background-color 120ms ease;
  }
  .mc-btn:hover { border-color: var(--sg-accent, #3b82f6); }
  .mc-btn.is-on { border-color: var(--sg-accent, #3b82f6); background: color-mix(in oklab, var(--sg-accent, #3b82f6) 12%, transparent); }
  .mc-join { font-size: 9px; font-weight: 800; letter-spacing: 0.05em; color: var(--sg-on-accent, #fff); background: var(--sg-accent, #3b82f6); border-radius: 4px; padding: 1px 5px; }
  .mc-or { background: #8b5cf6; }
</style>

View this example on GitHub

More Filtering & Search examples

  • Sort, filter, paginate - Three most-asked-for features wired together against ~5k rows.
  • Excel-style filters - Per-column operator dropdown with active-filter chips and clear.
  • Filter - between operator - Number + date columns expose a "Between" operator with From/To inputs. Drive it via the menu or imperatively with api.setFilter(id, { operator: "between", value, valueTo }).
  • Highlighted search matches - External search input + a custom cell snippet that wraps matched substrings in <mark>. Filters the dataset AND visually flags hits.
  • Find in grid (Ctrl+F) - Built-in find overlay with next / previous navigation. Scans every visible cell value; matches activate + scroll into view.