FreeGridv1.6.0한국어

Filtering

Each column's ⋮ menu holds a filter that matches its type: text (contains, equals, starts/ends with, blank…), number (=, ≠, <, ≤, >, ≥, between, blank),…

Live demoFiltering

Text, number, date and set filters plus a quick search box.

Code for this demo
import { createGrid } from '@freegridjs/core';
import { demoColumns, makeRows } from '../data';
import { button, search, separator, text, tr, type DemoContext } from '../ui';

export default function mount(ctx: DemoContext) {
  const { lang } = ctx;
  const grid = createGrid(ctx.host, { columns: demoColumns(lang), data: makeRows(20_000), locale: lang });

  const count = text(ctx, '');
  const update = () => (count.textContent = tr(lang, {
    en: `${grid.getDisplayedRowCount().toLocaleString()} of 20,000 rows`,
    ko: `20,000행 중 ${grid.getDisplayedRowCount().toLocaleString()}행`,
  }));
  grid.on('filterChange', e => {
    ctx.log(`filterChange → ${JSON.stringify(e.filters)}`);
    update();
  });

  search(ctx, tr(lang, { en: 'Quick search, e.g. "kim seoul"', ko: '빠른 검색 예: "kim japan"' }), q => {
    grid.setQuickFilter(q);
    update();
  });
  separator(ctx);
  button(ctx, tr(lang, { en: 'Q1 ≥ 80,000', ko: '1분기 ≥ 80,000' }), () => grid.setFilter('q1', { type: 'number', op: 'gte', value: 80000 }));
  button(ctx, tr(lang, { en: 'Joined in 2024', ko: '2024년 가입' }), () =>
    grid.setFilter('joined', { type: 'date', op: 'between', value: '2024-01-01', valueTo: '2024-12-31' }));
  button(ctx, tr(lang, { en: 'Japan or Korea', ko: '일본 또는 한국' }), () =>
    grid.setFilter('country', { type: 'set', values: ['Japan', 'South Korea'] }));
  button(ctx, tr(lang, { en: 'Clear filters', ko: '필터 모두 해제' }), () => {
    for (const id of Object.keys(grid.getFilterModel())) grid.setFilter(id, null);
  });
  update();
  return grid;
}

Live demoAdvanced filter

Two conditions per column with And / Or, and conditions across columns from a builder.

Code for this demo
import { createGrid } from '@freegridjs/core';
import { demoColumns, makeRows } from '../data';
import { button, separator, text, tr, type DemoContext } from '../ui';

export default function mount(ctx: DemoContext) {
  const { lang } = ctx;
  const h = (en: string, ko: string) => tr(lang, { en, ko });
  const grid = createGrid(ctx.host, { columns: demoColumns(lang), data: makeRows(2000), locale: lang, statusBar: true });
  grid.on('advancedFilterChange', e => ctx.log(`advancedFilterChange → ${JSON.stringify(e.advancedFilter)}`));
  grid.on('filterChange', e => ctx.log(`filterChange → ${JSON.stringify(e.filters)}`));

  text(ctx, h('Open a column menu: it takes two conditions joined with And / Or. Conditions across columns: right-click → Advanced filter…',
    '컬럼 메뉴에서 조건 두 개를 그리고/또는으로 묶을 수 있습니다. 여러 컬럼에 걸친 조건은 우클릭 → 고급 필터…'));
  separator(ctx);
  button(ctx, h('Q1 between 20,000 and 40,000', '1분기 2만~4만'), () =>
    grid.setFilter('q1', { type: 'combined', operator: 'and', conditions: [{ type: 'number', op: 'gte', value: 20000 }, { type: 'number', op: 'lte', value: 40000 }] }));
  button(ctx, h('(Japan and Q4 > 80,000) or name starts with "Kim"', '(일본 그리고 4분기 > 8만) 또는 이름이 Kim으로 시작'), () =>
    grid.setAdvancedFilter({ operator: 'or', conditions: [
      { operator: 'and', conditions: [
        { colId: 'country', model: { type: 'text', op: 'equals', value: 'Japan' } },
        { colId: 'q4', model: { type: 'number', op: 'gt', value: 80000 } },
      ] },
      { colId: 'name', model: { type: 'text', op: 'startsWith', value: 'kim' } },
    ] }));
  button(ctx, h('Open the builder', '조건 작성 창 열기'), () => grid.openFilterBuilder());
  button(ctx, h('Clear', '모두 해제'), () => {
    grid.setAdvancedFilter(null);
    grid.setFilter('q1', null);
  });
  return grid;
}

Each column's ⋮ menu holds a filter that matches its type: text (contains, equals, starts/ends with, blank…), number (=, ≠, <, ≤, >, ≥, between, blank), date (equals, before, after, between) and set (a searchable checklist of the column's values). Text matching ignores case. A filled filter icon marks filtered columns.

grid.setFilter('name', { type: 'text', op: 'contains', value: 'kim' });
grid.setFilter('total', { type: 'number', op: 'between', value: 1000, valueTo: 5000 });
grid.setFilter('joined', { type: 'date', op: 'after', value: '2025-01-01' });
grid.setFilter('country', { type: 'set', values: ['Japan', 'South Korea'] });
grid.setFilter('name', null);   // clear one
grid.setQuickFilter('kim seoul'); // every word must match some visible column
grid.on('filterChange', e => console.log(e.filters));

The column menu takes up to two conditions joined with and / or. Conditions across columns come from setAdvancedFilter or "Advanced filter…" in the right-click menu; they nest and apply together with the column filters.

// two conditions on one column
grid.setFilter('qty', { type: 'combined', operator: 'and',
  conditions: [{ type: 'number', op: 'gte', value: 10 }, { type: 'number', op: 'lte', value: 100 }] });

// (status = done AND amount > 100) OR customer starts with "Kim"
grid.setAdvancedFilter({ operator: 'or', conditions: [
  { operator: 'and', conditions: [
    { colId: 'status', model: { type: 'text', op: 'equals', value: 'done' } },
    { colId: 'amount', model: { type: 'number', op: 'gt', value: 100 } },
  ] },
  { colId: 'customer', model: { type: 'text', op: 'startsWith', value: 'kim' } },
] });
grid.openFilterBuilder();   // or right-click → Advanced filter…

Filter row

filterRow: true puts a box under every header that filters as you type (applied after 0.2 s; Enter applies at once, Escape clears). Type what fits the column, as below. Text the grid cannot read turns the box red and leaves the filter as it was.

ColumnTypeMeans
TextkimValues containing "kim" (any case)
Number15 · >10 · >=10 · <5 · <=5 · <>3Equal, greater, at least, less, at most, not equal (1,000 and currency signs are read too)
Number range10~20 · 10..20From 10 to 20
Date2026-03-05 · >2026-01-01 · <2026-12-31That day, after, before (dots or slashes work too: 2026.3.5)
Date range2026-01-01~2026-03-31Between the two days, both included
Set and true/falseA drop-downColumns with filter: 'set' and boolean columns pick one value

The filter row, the column menu and setFilter() share one filter, so a change in one shows in the others. Leave a column out with filter: false. What you are typing stays put when live updates change the rows.

const grid = createGrid(el, {
  columns: [
    { field: 'name', header: 'Name' },                   // text: contains
    { field: 'qty', header: 'Qty', type: 'number' },     // >10, <=5, 10~20
    { field: 'joined', header: 'Joined', type: 'date' }, // >2026-01-01, 2026-01-01~2026-03-31
    { field: 'status', header: 'Status', filter: 'set' }, // a list of the column's values
    { field: 'memo', header: 'Memo', filter: false },    // no box
  ],
  data,
  filterRow: true,
});

// the boxes and the column menu share one filter: setting one updates the other
grid.setFilter('qty', { type: 'number', op: 'between', value: 10, valueTo: 20 }); // the box shows 10~20

Questions about this page

What filters does FreeGrid have?

Text, number, date and set (list of values) filters in the column menu, a filter row under the header, a quick search box, and an advanced filter that combines conditions across columns with AND and OR.