Date editor (calendar)
A calendar under the cell for date columns: pick or type a day, move by day, month or year from the keyboard, limit the days with min, max and disabledDates.
Live demoDate editor
A calendar for date columns, with limits and keyboard moves.
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';
export default function mount(ctx: DemoContext) {
const h = (en: string, ko: string) => tr(ctx.lang, { en, ko });
const columns: ColumnDef[] = [
{ field: 'name', header: h('Name', '이름'), width: 160 },
// the calendar is the default editor of date columns
{ field: 'joined', header: h('Joined', '가입일'), type: 'date', width: 140, editable: true },
// limits: this year only, no weekends, weeks start on Monday
{ field: 'visit', header: h('Visit (weekdays, this year)', '방문일(평일, 올해)'), type: 'date', width: 200, editable: true,
editor: { type: 'date', min: `${new Date().getFullYear()}-01-01`, max: `${new Date().getFullYear()}-12-31`, disabledDates: d => d.getDay() === 0 || d.getDay() === 6, weekStart: 1 } },
// a text column: stored as 'YYYY-MM-DD'
{ field: 'due', header: h('Due (text)', '마감(텍스트)'), width: 140, editable: true, editor: { type: 'date' } },
];
const data = makeRows(200).map(r => ({ ...r, visit: null, due: '' }));
const grid = createGrid(ctx.host, { columns, data, locale: ctx.lang });
grid.on('cellValueChanged', e => ctx.log(`${e.colId}: ${String(e.oldValue)} → ${String(e.newValue)}`));
text(ctx, h('Double-click a date. ↑ ↓ move a day, PageUp / PageDown a month, Shift a year; the year and month lists jump far.',
'날짜를 더블클릭하세요. ↑ ↓는 하루, PageUp / PageDown은 한 달, Shift는 1년씩 움직이고, 연·월 목록으로 멀리 이동합니다.'));
return grid;
}Date columns (type: 'date') edit with a calendar that opens under the cell. People can click a day, or type it in the box above the calendar; the calendar follows what they type. The same editor works on text columns with editor: { type: 'date' }, where the value is stored as 'YYYY-MM-DD' text.
Basic use
createGrid(el, {
columns: [
{ field: 'orderDate', header: 'Order date', type: 'date', editable: true }, // the calendar by default
{ field: 'due', header: 'Due', editable: true, editor: { type: 'date' } }, // a text column: stored as 'YYYY-MM-DD'
],
data,
});Double-click a cell, press Enter or F2, or start typing a digit to open the editor. A click on a day saves at once and closes the calendar; Enter saves what is in the box.
Options
| Name | Type | Description |
|---|---|---|
min / max | 'YYYY-MM-DD' | Date | The earliest and latest day that can be picked or typed. Days outside are greyed out, and typing one is refused with a message. |
disabledDates | (day: Date) => boolean | Return true for days that cannot be picked, such as weekends or holidays. They are crossed out in the calendar and refused when typed or pasted. |
weekStart | 0 – 6 | The first day of the week (0 Sunday … 6 Saturday). By default Sunday for English (US), Korean, Japanese and Chinese, Monday elsewhere. |
today | boolean | Show the Today button under the calendar (default true). It is disabled when today is outside min / max. |
{ field: 'visit', type: 'date', editable: true,
editor: {
type: 'date',
min: '2026-01-01',
max: new Date(2026, 11, 31),
disabledDates: d => d.getDay() === 0 || d.getDay() === 6, // no weekends
weekStart: 1, // weeks start on Monday
} }Keyboard
| Key | Does |
|---|---|
| ↑ / ↓ | One day earlier / later (the box and the calendar move together) |
| PageUp / PageDown | One month earlier / later |
| Shift + PageUp / PageDown | One year earlier / later |
| Enter | Save the date in the box and move down |
| Tab / Shift + Tab | Save and go to the next / previous editable cell |
| Esc | Close without saving |
The year and month lists at the top jump straight to a far date, such as a birthday decades ago; ‹ and › move one month.
What gets stored
| The cell had | After an edit |
|---|---|
| A Date object | A Date object (local midnight) |
| Text '2026-03-05' in a date column | Text in the same form |
| Anything in a text column with editor: 'date' | 'YYYY-MM-DD' text |
| Clear (button or empty box) | null |
The display follows the column format (short, long, Intl options) in the grid language; the editor box always shows YYYY-MM-DD so it can be typed in any language.
Paste, fill and validation
- Pasting
2026-03-05,2026.3.5or2026/3/5works like typing; days outsidemin/maxor on adisabledDatesday are skipped and counted in the paste result'sskipped. required,uniqueandvalidaterun after the calendar too, with the message under the cell.- Date and time together: use
format: 'datetime'(a date-time picker) oreditor: { type: 'time' }for the time of day only. - Filtering the same column: see Date filters — the column menu and the filter row open a calendar there too.
Questions about this page
How do I add a date picker to a grid cell?
Give the column type: 'date' and editable: true. The calendar is the default editor for date columns; editor: { type: 'date', min, max } adds limits.
Can people still type a date instead of clicking?
Yes. The box above the calendar takes 2026-03-05 and also 2026.3.5 or 2026/3/5; the calendar follows what is typed.