Date filters and relative dates
Filter dates by day, before, after, between and relative ranges (today, this week, this month, last N days) that follow the calendar, with calendars in the menu and the filter row.
Live demoDate filters
Relative dates, a range from the calendar, and period columns.
Code for this demo
import { createGrid, type ColumnDef, type Row } from '@freegridjs/core';
import { makeRows } from '../data';
import { button, separator, text, tr, type DemoContext } from '../ui';
const pad = (n: number) => String(n).padStart(2, '0');
const day = (d: Date) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
export default function mount(ctx: DemoContext) {
const h = (en: string, ko: string) => tr(ctx.lang, { en, ko });
// dates around today, so the relative filters find something
const data = makeRows(1000).map((r, i) => {
const d = new Date();
d.setDate(d.getDate() - ((i * 7) % 400) + 30);
const end = new Date(d);
end.setDate(end.getDate() + (i % 20));
return { ...r, ordered: d, period: `${day(d)} ~ ${day(end)}` };
});
const grid = createGrid(ctx.host, {
columns: [
{ field: 'name', header: h('Name', '이름'), width: 150 },
{ field: 'ordered', header: h('Ordered', '주문일'), type: 'date', width: 140 },
{ field: 'period', header: h('Contract period', '계약 기간'), width: 220, editor: { type: 'dateRange' } },
],
data, locale: ctx.lang, filterRow: true,
});
const count = text(ctx, '');
const show = () => (count.textContent = h(`${grid.getDisplayedRowCount()} rows`, `${grid.getDisplayedRowCount()}행`));
grid.on('filterChange', e => { ctx.log(JSON.stringify(e.filters)); show(); });
const f = (label: string, model: object) => button(ctx, label, () => grid.setFilter('ordered', model as never));
f(h('Today', '오늘'), { type: 'date', op: 'today' });
f(h('This week', '이번 주'), { type: 'date', op: 'thisWeek' });
f(h('This month', '이번 달'), { type: 'date', op: 'thisMonth' });
f(h('Last 30 days', '최근 30일'), { type: 'date', op: 'lastDays', days: 30 });
f(h('Next 14 days', '앞으로 14일'), { type: 'date', op: 'nextDays', days: 14 });
separator(ctx);
button(ctx, h('Periods touching this month', '이번 달과 겹치는 기간'), () => grid.setFilter('period', { type: 'date', op: 'thisMonth' }));
button(ctx, h('Clear', '모두 해제'), () => { grid.setFilter('ordered', null); grid.setFilter('period', null); });
text(ctx, h('Or use the calendar button in the filter row, and the date boxes of the column menu.', '필터 행의 달력 버튼과 컬럼 메뉴의 날짜 칸도 써 보세요.'));
show();
return grid;
}Date columns (type: 'date', and columns with a date or date-range editor) get a date filter. Dates are compared as local days, so the time of a Date value does not matter.
Operators
| Operator | Model | Passes when |
|---|---|---|
| Equals / Does not equal | { op: 'equals', value: '2026-03-05' } | That day / any other day (blanks do not pass Does not equal) |
| Before / After | { op: 'after', value: '2026-01-01' } | Strictly before / after the day |
| Between | { op: 'between', value: '2026-01-01', valueTo: '2026-03-31' } | From the first to the last day, both included |
| Today / Yesterday | { op: 'today' } | Today / yesterday, from the computer clock |
| This week / Last week | { op: 'thisWeek' } | Monday to Sunday of this / last week |
| This month / Last month | { op: 'lastMonth' } | The calendar month |
| This quarter | { op: 'thisQuarter' } | Jan–Mar, Apr–Jun, Jul–Sep or Oct–Dec |
| This year / Last year | { op: 'thisYear' } | 1 January to 31 December |
| In the last N days | { op: 'lastDays', days: 7 } | Today and the N − 1 days before |
| In the next N days | { op: 'nextDays', days: 30 } | Today and the N − 1 days after |
| Blank / Not blank | { op: 'blank' } | No date / any date |
Relative dates are worked out again every time the rows are filtered (and on reload), so a view saved as "this month" shows the current month next month too.
grid.setFilter('joined', { type: 'date', op: 'thisMonth' });
grid.setFilter('joined', { type: 'date', op: 'lastDays', days: 30 });
grid.setFilter('joined', { type: 'date', op: 'between', value: '2026-01-01', valueTo: '2026-03-31' });
// last month or this month
grid.setFilter('joined', { type: 'combined', operator: 'or', conditions: [{ type: 'date', op: 'lastMonth' }, { type: 'date', op: 'thisMonth' }] });Calendars in the menus
- Column menu: focus a date box and a calendar opens under it; a click writes the day. For Between, the second box opens next.
- Advanced filter: the same calendar opens under the box you fill, for date columns only.
- Filter row: the calendar button in the date box offers the relative choices on the left and a calendar on the right — click once for a day, twice for a range. The box then shows the choice, such as *This month* or
2026-01-01~2026-01-31. - For In the last / next N days, the value box becomes a number box for N.
Period columns
On a column whose cells are periods ('2026-03-01 ~ 2026-03-10', [start, end] or { start, end }), a row passes when its period overlaps the filter:
| Operator | Passes when |
|---|---|
| Equals a day | The period contains that day |
| Before / After | The period starts before / ends after the day |
| Between, relative dates | The period and the range share at least one day |
With a datasource
The grid turns relative dates into fixed days before asking the server (thisMonth → between with this month's first and last day; today → equals), and Does not equal into two conditions, so the server examples need no change.
Questions about this page
How do I show only this month in a grid?
setFilter('date', { type: 'date', op: 'thisMonth' }), or pick This month from the calendar button in the filter row. It is worked out again each time the rows are filtered, so a saved view stays current.