FreeGridv1.6.0한국어

Formatting and renderers

Numbers and dates are formatted with the browser's Intl APIs in the grid language, so 1234.5 becomes 1,234.5 in English and 1.234,5 in German. Use…

Live demoFormatting & renderers

Locale-aware number and date formats, custom cell renderers and classes.

Code for this demo
import { createGrid, type ColumnDef } from '@freegridjs/core';
import de from '@freegridjs/core/locales/de';
import ko from '@freegridjs/core/locales/ko';
import { makeRows } from '../data';
import { select, tr, type DemoContext } from '../ui';

export default function mount(ctx: DemoContext) {
  const { lang } = ctx;
  const h = (en: string, k: string) => tr(lang, { en, ko: k });
  const columns: ColumnDef[] = [
    { field: 'name', header: h('Name', '이름'), width: 170, pinned: 'left' },
    // number patterns: '#,##0', '#,##0.00', '0.0%', 'currency:USD', or Intl.NumberFormat options
    { field: 'total', header: h('Total (USD)', '합계 (USD)'), type: 'number', format: 'currency:USD', width: 140 },
    { field: 'q1', header: h('Q1 (2 decimals)', '1분기 (소수 2자리)'), type: 'number', format: '#,##0.00', width: 150 },
    { field: 'growth', header: h('Growth', '성장률'), type: 'number', format: '0.0%', width: 110,
      cellClass: p => (typeof p.value === 'number' && p.value < 0 ? 'neg' : 'pos') },
    // date presets: 'date', 'datetime', 'time', 'short', 'medium', 'long'
    { field: 'joined', header: h('Joined (long)', '가입일 (long)'), type: 'date', format: 'long', width: 190 },
    { field: 'active', header: h('Active', '활성'), type: 'boolean', width: 90 },
    // A renderer can return an element…
    { id: 'share', header: h('Share of max', '최대 대비 비율'), width: 170, valueGetter: r => r.total / 400000,
      renderer: p => {
        const bar = document.createElement('div');
        bar.className = 'bar';
        const fill = document.createElement('i');
        fill.style.width = `${Math.min(100, Number(p.value) * 100)}%`;
        bar.append(fill);
        return bar;
      } },
    // Return elements for anything built from data; a returned string is inserted as HTML.
    { field: 'email', header: h('Email', '이메일'), width: 280, renderer: p => {
        const a = document.createElement('a');
        a.href = `mailto:${encodeURIComponent(String(p.value))}`;
        a.textContent = String(p.value); // textContent never interprets HTML
        return a;
      } },
  ];
  const grid = createGrid(ctx.host, { columns, data: makeRows(2000), locale: lang === 'ko' ? ko : 'en' });

  select(ctx, tr(lang, { en: 'Format locale', ko: '서식 로케일' }), [['en', 'English (en)'], ['ko', '한국어 (ko)'], ['de', 'Deutsch (de)']],
    lang, v => grid.setLocale(v === 'ko' ? ko : v === 'de' ? de : 'en'));
  return grid;
}

Numbers and dates are formatted with the browser's Intl APIs in the grid language, so 1234.5 becomes 1,234.5 in English and 1.234,5 in German. Use renderer for anything else; it gets value, formatted, row, rowIndex and column.

{ field: 'total', type: 'number', format: '#,##0' }       // 1,234
{ field: 'rate', type: 'number', format: '0.0%' }          // 12.5%
{ field: 'price', type: 'number', format: 'currency:KRW' } // ₩12,000
{ field: 'price', type: 'number', format: { maximumSignificantDigits: 3 } } // Intl options
{ field: 'joined', type: 'date', format: 'long' }          // 2026년 3월 5일 (ko)

// element renderer
{ field: 'status', renderer: p => {
    const b = document.createElement('span');
    b.className = `badge badge-${p.value}`;
    b.textContent = p.formatted;
    return b;
} }

A renderer that returns a string is inserted as HTML. Escape anything that comes from users, or return an element.