DGDataGrid

Features

๊ธฐ๋Šฅ๋ณ„ ๋ฐ๋ชจ โ€” ๊ฐ ์˜ˆ์ œ์˜ View Source ํƒญ์— ํ‘œ์‹œ๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ๊ทธ๋Œ€๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ณต์‚ฌํ•ด์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์™„๊ฒฐ๋œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. ์™ผ์ชฝ ๋ชฉ๋ก์—์„œ ์„ฑ๊ฒฉ๋ณ„๋กœ ๋ฌถ์ธ ์˜ˆ์ œ๋ฅผ ์ฐพ๊ฑฐ๋‚˜, ๊ฒ€์ƒ‰์ฐฝ(/)์— ์˜ต์…˜ ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด ๊ฑธ๋Ÿฌ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ Basics

์ •๋ ฌยทํ•„ํ„ฐยท์„ ํƒยทํŽ˜์ด์ง€๋„ค์ด์…˜ โ€” ๋Œ€๋ถ€๋ถ„์˜ ๊ทธ๋ฆฌ๋“œ๊ฐ€ ๊ฐ€์žฅ ๋จผ์ € ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒƒ๋“ค.

Sorting

ํ—ค๋” ํด๋ฆญ์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ โ†’ ๋‚ด๋ฆผ์ฐจ์ˆœ โ†’ ํ•ด์ œ ์ˆœํ™˜. Shift+ํด๋ฆญ์œผ๋กœ ๋‹ค์ค‘ ์ •๋ ฌ(์ •๋ ฌ ์ˆœ์„œ ๋ฐฐ์ง€ ํ‘œ์‹œ). sortModel๋กœ ์ดˆ๊ธฐ ์ •๋ ฌ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Column Filters

ํ—ค๋”์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ๋‚˜ํƒ€๋‚˜๋Š” ๋ฉ”๋‰ด ๋ฒ„ํŠผ์œผ๋กœ ์ปฌ๋Ÿผ๋ณ„ ํ•„ํ„ฐ๋ฅผ ์—ฝ๋‹ˆ๋‹ค. filter: 'text' ยท 'number' ยท 'set'. ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ ํ•„ํ„ฐ๋Š” AND๋กœ ๊ฒฐํ•ฉ๋ฉ๋‹ˆ๋‹ค.

Floating Filter (ํ—ค๋” ํ•„ํ„ฐ ํ–‰)

floatingFilter: true โ€” ํ—ค๋” ๋ฐ”๋กœ ์•„๋ž˜์— ์ปฌ๋Ÿผ๋ณ„ ์ธ๋ผ์ธ ํ•„ํ„ฐ ์ž…๋ ฅ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. text/number๋Š” ์ž…๋ ฅํ•˜๋Š” ๋Œ€๋กœ(250ms ๋””๋ฐ”์šด์Šค) ํ•„ํ„ฐ๋ง๋˜๊ณ , set์€ ๋“œ๋กญ๋‹ค์šด์œผ๋กœ ๋‹จ์ผ ๊ฐ’์„ ๊ณ ๋ฆ…๋‹ˆ๋‹ค. ํ•„ํ„ฐ ๋ฉ”๋‰ด์™€ ๊ฐ™์€ ํ•„ํ„ฐ ๋ชจ๋ธ์„ ๊ณต์œ ํ•˜๋ฏ€๋กœ Esc๋กœ ์ง€์šฐ๊ฑฐ๋‚˜ ๋ฉ”๋‰ด์—์„œ ๋ฐ”๊พผ ๋‚ด์šฉ์ด ์„œ๋กœ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.

ํ—ค๋” ์•„๋ž˜ ์ž…๋ ฅ๋ž€์— ๋ฐ”๋กœ ์ž…๋ ฅํ•ด ๋ณด์„ธ์š”.

Quick Filter

๋ชจ๋“  ์ปฌ๋Ÿผ์„ ๋Œ€์ƒ์œผ๋กœ ํ•œ ์ „์—ญ ๊ฒ€์ƒ‰ โ€” ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ชจ๋“  ๋‹จ์–ด๊ฐ€ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ณ ๊ธ‰ ํ•„ํ„ฐ (Advanced Filter)

advancedFilter: true โ€” AND/OR ๊ทธ๋ฃน์„ 3๋‹จ๊นŒ์ง€ ์ค‘์ฒฉํ•œ ์กฐ๊ฑด ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ปฌ๋Ÿผ ํ•„ํ„ฐ์™€ ๋ฐฐํƒ€๊ฐ€ ์•„๋‹ˆ๋ผ AND๋กœ ํ•ฉ์„ฑ๋˜๋ฉฐ, ์ง€๊ธˆ ๊ฑธ๋ฆฐ ์‹์€ ํ•ญ์ƒ ๊ทธ๋ฆฌ๋“œ ์œ„ ์š”์•ฝ ๋ฐ”์— ๋ณด์ž…๋‹ˆ๋‹ค. ๋‚ ์งœ ๋น„๊ต(before/after)์™€ ๋นˆ ๊ฐ’(blank/notBlank)์€ ๊ณ ๊ธ‰ ํ•„ํ„ฐ์—๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค. API๋Š” setAdvancedFilterModel() ยท getAdvancedFilterModel() ยท clearAdvancedFilter() ยท openAdvancedFilterBuilder().

ํ”„๋ฆฌ์…‹์„ ์ ์šฉํ•˜๊ฑฐ๋‚˜ โ€œ๋นŒ๋” ์—ด๊ธฐโ€๋กœ ์ง์ ‘ ์กฐ๊ฑด์„ ์กฐ๋ฆฝํ•ด ๋ณด์„ธ์š”.

Row Selection

rowSelection: 'multiple' โ€” ์ฒดํฌ๋ฐ•์Šค, ํ—ค๋” ์ „์ฒด ์„ ํƒ(๋ถ€๋ถ„ ์„ ํƒ ์‹œ indeterminate), Ctrl/โŒ˜+ํด๋ฆญ ํ† ๊ธ€, Shift+ํด๋ฆญ ๋ฒ”์œ„ ์„ ํƒ.

์„ ํƒ๋œ ํ–‰ ์—†์Œ

Pagination

ํŽ˜์ด์ง€ ํฌ๊ธฐ ์„ ํƒ, ์ฒ˜์Œ/์ด์ „/๋ฒˆํ˜ธ/๋‹ค์Œ/๋งˆ์ง€๋ง‰ ๋ฒ„ํŠผ, "X to Y of Z" ์š”์•ฝ. ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ๋„๋ฉด ์ „์ฒด ๊ฐ€์ƒ ์Šคํฌ๋กค๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

Basic Click & Pagination Events

cellClicked ยท rowClicked ยท rowDoubleClicked ์ด๋ฒคํŠธ๋Š” ํด๋ฆญํ•œ ์…€/ํ–‰์˜ payload๋ฅผ ์ „๋‹ฌํ•˜๊ณ , paginationChanged๋Š” ํŽ˜์ด์ง€ ์ด๋™ยทํŽ˜์ด์ง€ ํฌ๊ธฐ ๋ณ€๊ฒฝ ๋•Œ { page, pageSize }๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค (page๋Š” 0๋ถ€ํ„ฐ).

์…€ ํด๋ฆญยท๋”๋ธ”ํด๋ฆญ, ํŽ˜์ด์ง€ ์ด๋™์„ ํ•ด๋ณด๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ปฌ๋Ÿผ Columns

์ปฌ๋Ÿผ ์ •์˜ยทํ‘œ์‹œยทํ—ค๋” ๊ตฌ์„ฑ. ๊ฐ’์„ ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์ค„์ง€์™€ ํ—ค๋”๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฌถ์„์ง€.

Column Pinning ยท Resize ยท Reorder

pinned: 'left' | 'right' ๊ณ ์ • ์ปฌ๋Ÿผ(์Šคํฌ๋กค ์‹œ ๊ทธ๋ฆผ์ž), ํ—ค๋” ๊ฒฝ๊ณ„ ๋“œ๋ž˜๊ทธ๋กœ ํฌ๊ธฐ ์กฐ์ ˆ, ๊ฒฝ๊ณ„ ๋”๋ธ”ํด๋ฆญ์œผ๋กœ ์ž๋™ ๋งž์ถค, ํ—ค๋” ๋“œ๋ž˜๊ทธ๋กœ ์ˆœ์„œ ๋ณ€๊ฒฝ.

Column Visibility & Auto-size

column.hide๋กœ ์ดˆ๊ธฐ ์ˆจ๊น€์„ ์ง€์ •ํ•˜๊ณ , setColumnVisible(colId, visible)๋กœ ๋Ÿฐํƒ€์ž„์— ํ† ๊ธ€ํ•ฉ๋‹ˆ๋‹ค. getColumns()๋Š” ์ •๊ทœํ™”๋œ ์ปฌ๋Ÿผ ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  (์•„๋ž˜ ์ฒดํฌ๋ฐ•์Šค๊ฐ€ ์ด ๋ชฉ๋ก์œผ๋กœ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค), autoSizeColumn(colId)์€ ๋‚ด์šฉ ํญ์— ๋งž์ถฐ ์ปฌ๋Ÿผ ํญ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค (ํ—ค๋” ๊ฒฝ๊ณ„ ๋”๋ธ”ํด๋ฆญ๊ณผ ๋™์ผ).

์ฒดํฌ๋ฐ•์Šค๋กœ ์ปฌ๋Ÿผ์„ ์ผœ๊ณ  ๊บผ ๋ณด์„ธ์š”. Email์€ hide: true๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

Row Numbers ยท Max Width ยท Grid-level Editable

rowNumbers: true๋Š” ์™ผ์ชฝ์— ๊ณ ์ •๋œ ํ–‰ ๋ฒˆํ˜ธ ์ปฌ๋Ÿผ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(์ •๋ ฌยทํ•„ํ„ฐยท๋ณต์‚ฌ ์ œ์™ธ). column.maxWidth๋Š” ๋“œ๋ž˜๊ทธ ๋ฆฌ์‚ฌ์ด์ฆˆยทflexยท์ž๋™ ๋งž์ถค์˜ ์ƒํ•œ์ด ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๋“œ ๋ ˆ๋ฒจ editable: false / setEditable(bool)์€ ์ปฌ๋Ÿผ ์„ค์ •์„ ๋ฌด์‹œํ•˜๊ณ  ํŽธ์ง‘ ์ „์ฒด๋ฅผ ์ž ๊ธ‰๋‹ˆ๋‹ค.

์ง€๊ธˆ์€ ํŽธ์ง‘ ์ž ๊น€(editable: false) โ€” Name์„ ๋”๋ธ”ํด๋ฆญํ•ด๋„ ํŽธ์ง‘๊ธฐ๊ฐ€ ์—ด๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. City๋Š” maxWidth: 160์ด๋ผ ๊ทธ ์ด์ƒ ๋„“ํž ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

Column Data Type & Declarative Format

dataType: 'number' | 'date' | 'bool'์€ ์ •๋ ฌ ๋น„๊ตยท filter: true์˜ ํ•„ํ„ฐ ์ข…๋ฅ˜ยท๊ธฐ๋ณธ ์ •๋ ฌ ๋ฐฉํ–ฅ(์ˆซ์ž๋Š” ์˜ค๋ฅธ์ชฝ)์„ ์ž๋™ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. format: '$#,##0.00' / 'yyyy-MM-dd' ์„ ์–ธ์  ํฌ๋งท์€ valueFormatter๋ฅผ ๋Œ€์‹ ํ•˜๋ฉฐ, ๊ฐ™์€ ํŒจํ„ด์„ DataGrid.format(value, pattern) ์œ ํ‹ธ๋กœ๋„ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Salary/Rating์€ dataType: 'number' โ€” ํ—ค๋” ํด๋ฆญ ์ •๋ ฌ์ด ์ˆซ์ž ๊ธฐ์ค€์ด๊ณ  ์ž๋™ ์šฐ์ธก ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค.

Column Group Headers

columnGroups: [{ headerName, children: ['field'...] }]๋Š” ํ—ค๋” ์œ„์— ๊ทธ๋ฃน ์ŠคํŒฌ ํ–‰์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ๊ทธ๋ฃน์˜ ์—ฐ์†๋œ ์ปฌ๋Ÿผ์ด ํ•˜๋‚˜์˜ ์ŠคํŒฌ์œผ๋กœ ๋ฌถ์ด๊ณ , ์ปฌ๋Ÿผ์„ ๋“œ๋ž˜๊ทธํ•ด ๊ทธ๋ฃน ๋ฐ–์œผ๋กœ ์˜ฎ๊ธฐ๋ฉด ์ŠคํŒฌ์ด ์ž๋™์œผ๋กœ ๊ฐˆ๋ผ์ง‘๋‹ˆ๋‹ค. ๊ณ ์ •(pinned) ์ปฌ๋Ÿผ ๊ฒฝ๊ณ„์—์„œ๋Š” ์ŠคํŒฌ์ด ๋Š๊ฒจ ์Šคํฌ๋กค๊ณผ ์–ด๊ธ‹๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ปฌ๋Ÿผ ํ—ค๋”๋ฅผ ๋“œ๋ž˜๊ทธํ•ด ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ” ๋ณด์„ธ์š” โ€” ๊ทธ๋ฃน ์ŠคํŒฌ์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์žฌ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

Nested Column Group Headers (3๋‹จ ํ—ค๋”)

columnGroups์˜ children์— ์ปฌ๋Ÿผ ์ด๋ฆ„ ๋Œ€์‹  ๊ทธ๋ฃน ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ๋„ฃ์œผ๋ฉด ๊ทธ๋ฃน ์ค„์ด ํ•œ ์ค„ ๋” ์ƒ๊ฒจ 3๋‹จ ํ—ค๋”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ž์‹ ๊ทธ๋ฃน์ด ์—†๋Š” ๊ตฌ๊ฐ„์€ ์ƒ์œ„ ๊ทธ๋ฃน์ด ๋‘ ์ค„์„ ์ฐจ์ง€ํ•ด ๋ผ๋ฒจ์ด ๊ฐ€์šด๋ฐ์— ๋†“์ž…๋‹ˆ๋‹ค โ€” ๊ทธ๋ž˜์„œ ๊นŠ์ด๊ฐ€ ์„ž์—ฌ ์žˆ์–ด๋„ ํ‘œ๊ฐ€ ๋“ค์ญ‰๋‚ ์ญ‰ํ•ด ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ค„ ์ˆ˜๋Š” ์„ค์ •์ด ์•„๋‹ˆ๋ผ ์ง€๊ธˆ ๋ณด์ด๋Š” ์ปฌ๋Ÿผ์— ์‹ค์ œ๋กœ ๊ฑธ๋ฆฐ ๊นŠ์ด๋กœ ์ •ํ•ด์ง€๋ฏ€๋กœ, ํ•˜์œ„ ๊ทธ๋ฃน ์ปฌ๋Ÿผ์„ ์ „๋ถ€ ์ˆจ๊ธฐ๋ฉด ๊ทธ ์ค„์ด ์ €์ ˆ๋กœ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์ปฌ๋Ÿผ ํ—ค๋”๋ฅผ ๋“œ๋ž˜๊ทธํ•ด ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ์œ„ ๋ฒ„ํŠผ์œผ๋กœ ์ปฌ๋Ÿผ์„ ์ˆจ๊ฒจ ๋ณด์„ธ์š” โ€” ๊ทธ๋ฃน ์ค„ ์ˆ˜๊ฐ€ ๋”ฐ๋ผ ๋ฐ”๋€๋‹ˆ๋‹ค.

Custom Header (headerRenderer / headerClass / headerTooltip)

column.headerRenderer(params)๋Š” ํ—ค๋” ๋ผ๋ฒจ์„ ์ปค์Šคํ…€ ์ฝ˜ํ…์ธ (HTML ๋ฌธ์ž์—ด ๋˜๋Š” Element)๋กœ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค โ€” cellRenderer์˜ ํ—ค๋”ํŒ. ์ •๋ ฌยทํ•„ํ„ฐ ๋ฉ”๋‰ดยท๋ฆฌ์‚ฌ์ด์ฆˆยท๋ฆฌ์˜ค๋”๋Š” ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•˜๊ณ , ์ปค์Šคํ…€ ํ—ค๋” ์•ˆ์˜ ๋ฒ„ํŠผยท์ž…๋ ฅ ๋“ฑ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์š”์†Œ ํด๋ฆญ์€ ์ •๋ ฌ์„ ๋ฐœ๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. headerClassยทheaderTooltip์œผ๋กœ ํด๋ž˜์Šค์™€ ํˆดํŒ๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Salary ํ—ค๋”์˜ ฮฃ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด ๋ณด์„ธ์š” โ€” ์ •๋ ฌ ์—†์ด ํ•ฉ๊ณ„๋งŒ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค. ๋ผ๋ฒจ ์˜์—ญ ํด๋ฆญ์€ ์ •๋ ฌ.

Computed Columns & Row Styling

column.valueGetter(row)๋Š” ํŒŒ์ƒ ๊ฐ’์„ ๊ณ„์‚ฐํ•ด ํ–‰์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค โ€” ์ •๋ ฌยทํ•„ํ„ฐยทCSV/JSON ๋‚ด๋ณด๋‚ด๊ธฐ ๋ชจ๋‘ ๊ฐ™์€ ๊ฐ’์„ ๋ด…๋‹ˆ๋‹ค. getRowClass(row, index)๋Š” ํ–‰๋ณ„ CSS ํด๋ž˜์Šค๋ฅผ, column.suppressMove๋Š” ํŠน์ • ์ปฌ๋Ÿผ์˜ ๋“œ๋ž˜๊ทธ ์ด๋™์„ ๋ง‰์Šต๋‹ˆ๋‹ค.

Total์€ Qty ร— Unit Price๋กœ ๊ณ„์‚ฐ๋œ ์ปฌ๋Ÿผ์ž…๋‹ˆ๋‹ค โ€” Qty๋ฅผ ๋”๋ธ”ํด๋ฆญํ•ด ์ˆ˜์ •ํ•˜๋ฉด Totalยท์ •๋ ฌ์ด ํ•จ๊ป˜ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค. ํ•ฉ๊ณ„ $2,000 ์ด์ƒ ํ–‰์€ ๊ฐ•์กฐ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. Order ID๋Š” suppressMove๋ผ ๋“œ๋ž˜๊ทธ๋กœ ์˜ฎ๊ธธ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

Merge Cells (์—ฐ์† ๊ฐ’ ์„ธ๋กœ ๋ณ‘ํ•ฉ)

mergeCells: ['field'...]๋Š” ํ‘œ์‹œ ์ˆœ์„œ์ƒ ์—ฐ์†๋œ ๊ฐ™์€ ๊ฐ’์„ ์„ธ๋กœ๋กœ ๋ณ‘ํ•ฉํ•ด ๋ณด์—ฌ์ค๋‹ˆ๋‹ค โ€” ๋ณ‘ํ•ฉ ๊ตฌ๊ฐ„์ด ํ•˜๋‚˜์˜ ์…€์ด ๋˜์–ด ๊ฐ’์ด ์„ธ๋กœ ์ค‘์•™์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์ปฌ๋Ÿผ์œผ๋กœ ์ •๋ ฌํ•˜๋ฉด ๋ณ‘ํ•ฉ ํšจ๊ณผ๊ฐ€ ์ปค์ง€๊ณ , ๊ทธ๋ฃน ํ—ค๋”ยท๋””ํ…Œ์ผ ํ–‰์—์„œ๋Š” ๋ณ‘ํ•ฉ์ด ๋Š๊น๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ๋ผ CSV/ํด๋ฆฝ๋ณด๋“œ์—๋Š” ์˜ํ–ฅ์ด ์—†์Šต๋‹ˆ๋‹ค.

ProductยทStatus ์ปฌ๋Ÿผ์ด ๋ณ‘ํ•ฉ ๋Œ€์ƒ์ž…๋‹ˆ๋‹ค โ€” ํ—ค๋”๋ฅผ ํด๋ฆญํ•ด ์ •๋ ฌ์„ ๋ฐ”๊พธ๋ฉด ๋ณ‘ํ•ฉ์ด ์žฌ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

ํŽธ์ง‘ Editing

์ธ๋ผ์ธ ์…€ ํŽธ์ง‘ โ€” ์—๋””ํ„ฐ ์ข…๋ฅ˜, ๊ฒ€์ฆ, ํŽธ์ง‘ ๊ฐ€๋Šฅ ๋ฒ”์œ„ ์ œ์–ด.

Cell Editing

editable: true ์…€์„ ๋”๋ธ”ํด๋ฆญ(๋˜๋Š” Enter)ํ•˜๋ฉด ํŽธ์ง‘ ์‹œ์ž‘ โ€” text / number / select ์—๋””ํ„ฐ, Enter ์ปค๋ฐ‹, Esc ์ทจ์†Œ, cellValueChanged ์ด๋ฒคํŠธ ๋ฐœํ–‰.

์…€์„ ๋”๋ธ”ํด๋ฆญํ•ด ํŽธ์ง‘ํ•ด ๋ณด์„ธ์š”.

Edit Validation & Programmatic Control

column.validator(value, row)๊ฐ€ true๊ฐ€ ์•„๋‹Œ ๊ฐ’(์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ๋ฌธ์ž์—ด)์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ปค๋ฐ‹์ด ๊ฑฐ๋ถ€๋˜๊ณ  ํŽธ์ง‘๊ธฐ๊ฐ€ ๋นจ๊ฐ„ ํ…Œ๋‘๋ฆฌ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค(Esc๋กœ ์ทจ์†Œ). beforeCellSave ์ด๋ฒคํŠธ์—์„œ e.cancel = true๋กœ ์ €์žฅ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๊ณ , startEdit(row, field) / stopEdit(commit) / isEditing()์œผ๋กœ ํŽธ์ง‘์„ ์ฝ”๋“œ๋กœ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ํŽธ์ง‘ ์ˆ˜๋ช…์ฃผ๊ธฐ๋Š” editingStarted / editingStopped๋กœ ๊ด€์ฐฐํ•ฉ๋‹ˆ๋‹ค.

Name์€ 2์ž ์ด์ƒ, Salary๋Š” 0 ~ 1,000,000๋งŒ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์…€์„ ๋”๋ธ”ํด๋ฆญํ•ด ์ž˜๋ชป๋œ ๊ฐ’์„ ๋„ฃ์–ด ๋ณด์„ธ์š”.

Continuous Editing & Custom Editor

editOnSingleClick(ํด๋ฆญ ํ•œ ๋ฒˆ ํŽธ์ง‘) ยท enterMovesDown(Enter๋กœ ์•„๋ž˜ ์…€ ์—ฐ์† ํŽธ์ง‘) ยท tabMovesRight(Tab/Shift+Tab์œผ๋กœ ์ขŒ์šฐ ์ด๋™, ํ–‰ ๋์—์„œ ์ค„๋ฐ”๊ฟˆ) ์˜ต์…˜๊ณผ, editor: { init(cell, value, row, col), getValue(), destroy() } ์ปค์Šคํ…€ ์—๋””ํ„ฐ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. Rating ์ปฌ๋Ÿผ์€ ์Šฌ๋ผ์ด๋” ์—๋””ํ„ฐ๋ฅผ ์”๋‹ˆ๋‹ค.

์•„๋ฌด ์…€์ด๋‚˜ ํด๋ฆญํ•˜๋ฉด ์ฆ‰์‹œ ํŽธ์ง‘ โ€” Enter๋Š” ์•„๋ž˜๋กœ, Tab์€ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

Editable Column Indicator (editableIndicator)

editableIndicator: true๋ฅผ ์ฃผ๋ฉด ํŽธ์ง‘ ๊ฐ€๋Šฅํ•œ ์ปฌ๋Ÿผ ํ—ค๋”์— ์—ฐํ•„ ์•„์ด์ฝ˜์ด ๋ถ™์Šต๋‹ˆ๋‹ค โ€” ์–ด๋–ค ์ปฌ๋Ÿผ์„ ๋”๋ธ”ํด๋ฆญํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ•œ๋ˆˆ์— ๋ณด์ž…๋‹ˆ๋‹ค. ํ‘œ์‹œ ๊ธฐ์ค€์€ ์ง€๊ธˆ ์‹ค์ œ๋กœ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€๋ผ์„œ, setEditable(false)๋กœ ๊ทธ๋ฆฌ๋“œ๋ฅผ ์ž ๊ทธ๋ฉด ์•„์ด์ฝ˜๋„ ํ•จ๊ป˜ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค(๊ฑฐ์ง“ ํ‘œ์‹œ ๋ฐฉ์ง€). ์•„๋ž˜ ๋ฒ„ํŠผ์œผ๋กœ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

Name ยท Department ยท Salary ํ—ค๋”์˜ ์—ฐํ•„ ์•„์ด์ฝ˜์ด ํŽธ์ง‘ ๊ฐ€๋Šฅ ํ‘œ์‹œ์ž…๋‹ˆ๋‹ค. (IDยทCity๋Š” ์ฝ๊ธฐ ์ „์šฉ)

Required Columns (column.required)

column.required: true๋Š” ํ‘œ์‹œ์™€ ๊ฒ€์ฆ์„ ํ•œ ๋ฒˆ์— ์ผญ๋‹ˆ๋‹ค โ€” ๋น„์–ด ์žˆ๋Š” ์…€์—๋งŒ ์˜ค๋ฅธ์ชฝ ์œ„ ๋ชจ์„œ๋ฆฌ ๋งˆ์ปค๊ฐ€ ๋‚˜ํƒ€๋‚˜๋ฉฐ, ๋นˆ ๊ฐ’ ์ปค๋ฐ‹์€ ์ธ๋ผ์ธ ํŽธ์ง‘ ยท ํŒ์—… ํผ ยท ๋ถ™์—ฌ๋„ฃ๊ธฐ ยท updateRows ์–ด๋А ๊ฒฝ๋กœ๋กœ๋„ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๋“œ ํ‘œ์‹œ๋Š” ์…€ ๋งˆ์ปค ํ•˜๋‚˜์ด๊ณ  ํ—ค๋”์—๋Š” ํ‘œ์‹์„ ๋‘์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ํ•„์ˆ˜ ์ปฌ๋Ÿผ์˜ ๋ชจ๋“  ์…€์— ๊ทธ๋ฆฌ๋ฉด ๋‹ค ๊ฐ™์€ ํ‘œ์‹œ๋ผ ์ •๋ณด๋Ÿ‰์ด 0์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. (* ํ‘œ์‹์€ ํŒ์—… ํผ ๋ผ๋ฒจ์—๋งŒ ๋ถ™์Šต๋‹ˆ๋‹ค โ€” ์•„๋ž˜ "์ฒซ ํ–‰ ํผ ํŽธ์ง‘"์œผ๋กœ ํ™•์ธํ•˜์„ธ์š”.) trackChanges์˜ ์ˆ˜์ •๋จ ๋งˆ์ปค(์™ผ์ชฝ ์œ„ ์ฃผํ™ฉ)์™€ ์ž๋ฆฌยท์ƒ‰์ด ๊ฒน์น˜์ง€ ์•Š๊ฒŒ ์˜ค๋ฅธ์ชฝ ์œ„ ๋นจ๊ฐ•์„ ์”๋‹ˆ๋‹ค โ€” ํ•œ ์…€์— ๋‘˜์ด ๋™์‹œ์— ๋œฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 0๊ณผ false๋Š” ์œ ํšจํ•œ ๊ฐ’์œผ๋กœ ์ทจ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ numberยทdate ์—๋””ํ„ฐ๋Š” ๋นˆ ์ž…๋ ฅ์ด ๊ธฐ์กด ์ •๊ทœํ™” ๊ทœ์น™์— ๋”ฐ๋ผ ์ด์ „ ๊ฐ’์œผ๋กœ ๋˜๋Œ์•„๊ฐ€๋ฏ€๋กœ ์• ์ดˆ์— ๋นˆ ๊ฐ’์ด ์ปค๋ฐ‹๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ์ธ๋ผ์ธ์—์„œ required ์˜ค๋ฅ˜๋ฅผ ๋ณด๋ ค๋ฉด ํ…์ŠคํŠธ ๊ณ„์—ด ์ปฌ๋Ÿผ(์•„๋ž˜ Department)์„ ์“ฐ์„ธ์š”.

City ยท Salary ยท Department๊ฐ€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. Department๋ฅผ ๋”๋ธ”ํด๋ฆญํ•ด ์ง€์šฐ๊ณ  Enter๋ฅผ ๋ˆŒ๋Ÿฌ ๋ณด์„ธ์š”.

Row / Cell Locking (setRowEnabled ยท setCellEnabled)

setRowEnabled(row, false)๋Š” ํ–‰์„, setCellEnabled(row, field, false)๋Š” ์…€์„ ์ž ๊ธ‰๋‹ˆ๋‹ค. ํ–‰ ์ž ๊ธˆ์€ ํŽธ์ง‘(์ธ๋ผ์ธยท๋ถ™์—ฌ๋„ฃ๊ธฐยท์ฑ„์šฐ๊ธฐยทํŒ์—… ํผ)๊ณผ ์„ ํƒ๊นŒ์ง€ ๋ง‰๊ณ  ํ๋ฆฌ๊ฒŒ ํ‘œ์‹œํ•˜๋ฉฐ, ์…€ ์ž ๊ธˆ์€ ํŽธ์ง‘ ๊ณ„์—ด๋งŒ ๋ง‰์Šต๋‹ˆ๋‹ค. ์ž ๊ธˆ ์ƒํƒœ๋Š” ๊ทธ๋ฆฌ๋“œ๊ฐ€ ๋“ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํ˜ธ์ถœ ํ•œ ๋ฒˆ์ด๋ฉด ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ๊นŒ์ง€ ๋๋‚˜๊ณ , setRowData()๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐˆ์•„๋ผ์šฐ๋ฉด ํ•จ๊ป˜ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ์กฐํšŒ๋Š” isRowEnabled(row) / isCellEnabled(row, field), ์ผ๊ด„ ํ•ด์ œ๋Š” resetEnabled()์ž…๋‹ˆ๋‹ค.

NameยทSalaryยทCity๋Š” ๋”๋ธ”ํด๋ฆญ์œผ๋กœ ํŽธ์ง‘๋ฉ๋‹ˆ๋‹ค. ์ž ๊ธด ํ–‰์€ ํŽธ์ง‘๋„ ์„ ํƒ๋„ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Date / DateTime Editor (editor: 'date' | 'datetime')

editor: 'date' / editor: 'datetime'์€ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋‚ ์งœ ํ”ผ์ปค (<input type="date"> / datetime-local)๋กœ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค. dataType: 'date'๋งŒ ์ค˜๋„ date ์—๋””ํ„ฐ๊ฐ€ ์ž๋™ ์„ ํƒ๋ฉ๋‹ˆ๋‹ค. ์ปค๋ฐ‹ ๊ฐ’์€ ์›๋ณธ ํƒ€์ž…์„ ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค โ€” ๋ฌธ์ž์—ด์ด์—ˆ์œผ๋ฉด ๋ฌธ์ž์—ด(์ปฌ๋Ÿผ format ํ‘œ๊ธฐ), Date์˜€์œผ๋ฉด Date, ํƒ€์ž„์Šคํƒฌํ”„ ์ˆซ์ž์˜€์œผ๋ฉด ์ˆซ์ž. editorOptions: { min, max }๋กœ ์„ ํƒ ๋ฒ”์œ„๋ฅผ ์ œํ•œํ•˜๊ณ , ์ž…๋ ฅ์„ ๋น„์šฐ๋ฉด null๋กœ ์ง€์›Œ์ง‘๋‹ˆ๋‹ค. ์•„๋ž˜ ์ƒํƒœ ์ค„์—์„œ ์ปค๋ฐ‹๋œ ๊ฐ’์˜ ํƒ€์ž…์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

๋‚ ์งœ ์…€์„ ๋”๋ธ”ํด๋ฆญํ•ด ํŽธ์ง‘ํ•ด ๋ณด์„ธ์š” โ€” ์ปค๋ฐ‹๋œ ๊ฐ’๊ณผ ํƒ€์ž…์ด ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Select Editor โ€” label/value Options

editorOptions๋Š” ๋ฌธ์ž์—ด ๋ฐฐ์—ด ์™ธ์— { label: 'ํ•œ๊ตญ', value: 'kr' } ๊ฐ์ฒด ๋ฐฐ์—ด๋„ ๋ฐ›์Šต๋‹ˆ๋‹ค โ€” ๋“œ๋กญ๋‹ค์šด์—๋Š” label์ด ํ‘œ์‹œ๋˜๊ณ , ์„ ํƒํ•˜๋ฉด value๊ฐ€ ๋ฐ์ดํ„ฐ์— ์ €์žฅ๋˜์–ด ์…€์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค (์ˆซ์ž value๋Š” ํƒ€์ž…์ด ๋ณด์กด๋ฉ๋‹ˆ๋‹ค). editor๋ฅผ ์„ ์–ธํ•œ ์ปฌ๋Ÿผ์€ editable: true๋ฅผ ์ƒ๋žตํ•ด๋„ ํŽธ์ง‘์ด ์ผœ์ง‘๋‹ˆ๋‹ค (๋ช…์‹œ์  editable: false๊ฐ€ ์šฐ์„ ).

Country ์…€์„ ํด๋ฆญํ•ด ๋“œ๋กญ๋‹ค์šด์—์„œ ๋‚˜๋ผ ์ด๋ฆ„(label)์„ ๊ณ ๋ฅด๋ฉด ์…€์—๋Š” ์ฝ”๋“œ(value)๊ฐ€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

Searchable Select Editor (editorSearch)

editor: 'select'์— editorSearch๋ฅผ ์ฃผ๋ฉด ๋„ค์ดํ‹ฐ๋ธŒ ์…€๋ ‰ํŠธ ๋Œ€์‹  ๊ฒ€์ƒ‰ ์ž…๋ ฅ์ด ์žˆ๋Š” ์˜ต์…˜ ํŒจ๋„๋กœ ๋ฐ”๋€๋‹ˆ๋‹ค. editorSearch: true๋Š” ์ •์  editorOptions๋ฅผ ๋กœ์ปฌ์—์„œ ํ•„ํ„ฐํ•˜๊ณ , editorSearch: { fetch(query) }๋Š” ์งˆ์˜๋งˆ๋‹ค ๋น„๋™๊ธฐ๋กœ ๋ชฉ๋ก์„ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค (lazy ๊ฒ€์ƒ‰ โ€” debounceยทminLengthยท placeholder ์˜ต์…˜). ์ง๊ฟ ๋ Œ๋”๋Ÿฌ DataGrid.renderers.searchselect()๋Š” lazy ๊ฒ€์ƒ‰์œผ๋กœ ๊ณ ๋ฅธ(์ •์  ๋ชฉ๋ก์— ์—†๋Š”) ๊ฐ’๋„ ์„ ํƒ ๋‹น์‹œ์˜ label๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ํˆด๋ฐ” ์ฒดํฌ๋ฐ•์Šค๋กœ editOnSingleClick์„ ์ผœ์„œ ํด๋ฆญ ํ•œ ๋ฒˆ ํŽธ์ง‘๊ณผ ํ•จ๊ป˜ ํ…Œ์ŠคํŠธํ•ด ๋ณด์„ธ์š”.

Country๋Š” ์ •์  ๋ชฉ๋ก ๊ฒ€์ƒ‰(editorSearch: true), City๋Š” lazy ๊ฒ€์ƒ‰(fetch + 250ms ์ง€์—ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜)์ž…๋‹ˆ๋‹ค.

Multiselect ยท Radio ยท Checkbox Editors & Renderers

editor์— 'multiselect'(์ฒดํฌ๋ฆฌ์ŠคํŠธ ํŒจ๋„, ๊ฐ’์€ ๋ฐฐ์—ด)ยท 'radio'(๋‹จ์ผ ์„ ํƒ ๋ผ๋””์˜ค ํŒจ๋„)ยท'checkbox'(์ฒดํฌ๋ฐ•์Šค)๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ๊ฐ ์ง๊ฟ ๋ Œ๋”๋Ÿฌ DataGrid.renderers.multiselect()(label ์นฉ ๋ชฉ๋ก)ยท renderers.radio()(value โ†’ label)ยทrenderers.checkbox()(ํ‘œ์‹œ ์ „์šฉ ์ฒดํฌ๋ฐ•์Šค)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. multiselect๋Š” editorOptions ์ˆœ์„œ๋Œ€๋กœ ๋ฐฐ์—ด์„ ์ปค๋ฐ‹ํ•˜๋ฉฐ ๋‚ด์šฉ์ด ๊ฐ™์œผ๋ฉด ์ปค๋ฐ‹ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. checkbox๋Š” ๋ถˆ๋ฆฌ์–ธ ์™ธ์— editorOptions: { checked: 'Y', unchecked: 'N' } ๋งคํ•‘์œผ๋กœ Y/Nยท0/1 ๊ฐ™์€ ํ‘œ๊ธฐ๋„ ๊ทธ๋Œ€๋กœ ์ €์žฅยทํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

Skills(๋”๋ธ”ํด๋ฆญ โ†’ ์ฒดํฌ๋ฆฌ์ŠคํŠธ)ยทLevel(๋ผ๋””์˜ค)ยทRemote(์ฒดํฌ๋ฐ•์Šค) ์…€์„ ํŽธ์ง‘ํ•ด ๋ณด์„ธ์š”. Enter/๋ฐ”๊นฅ ํด๋ฆญ = ์ปค๋ฐ‹, Esc = ์ทจ์†Œ.

Searchable Multiselect Editor (multiselect + editorSearch)

editor: 'multiselect'์—๋„ editorSearch๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (v2.25). ์Šคํ‚ค๋งˆ๋Š” ๊ฒ€์ƒ‰ํ˜• select์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค โ€” true๋ฉด ์ •์  editorOptions๋ฅผ ๋กœ์ปฌ ํ•„ํ„ฐํ•˜๊ณ , { fetch(query) }๋ฉด ์งˆ์˜๋งˆ๋‹ค ๋น„๋™๊ธฐ๋กœ ๋ชฉ๋ก์„ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. ๊ณ ๋ฅธ ๊ฐ’์€ ์นฉ์œผ๋กœ ๊ฒ€์ƒ‰์ฐฝ ์œ„์— ์ƒ์‹œ ํ‘œ์‹œ๋˜๋ฏ€๋กœ, ํ•„ํ„ฐ๋กœ ๋ชฉ๋ก์—์„œ ๊ฐ€๋ ค์ง€๊ฑฐ๋‚˜ lazy ์งˆ์˜๋กœ ๋ชฉ๋ก์ด ํ†ต์งธ๋กœ ๊ฐˆ๋ ค๋„ ์ง€๊ธˆ ๋ฌด์—‡์ด ๊ณจ๋ผ์ ธ ์žˆ๋Š”์ง€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์นฉ์˜ ร— ๋˜๋Š” ํ•ญ๋ชฉ ์žฌํด๋ฆญ์œผ๋กœ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค. Enter๋Š” ๋ชฉ๋ก์ด ๋ณด์ผ ๋•Œ๋งŒ ํ™œ์„ฑ ํ•ญ๋ชฉ(โ†‘/โ†“๋กœ ๊ณ ๋ฅธ ๊ฒƒ)์„ ํ† ๊ธ€ํ•˜๊ณ , ๋ชฉ๋ก์ด ์ ‘ํ˜€ ์žˆ์œผ๋ฉด ์…€์—์„œ๋Š” ์ปค๋ฐ‹ ยท ํผ์—์„œ๋Š” ์ €์žฅ์œผ๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค โ€” ๋งˆ์šฐ์Šค๋กœ ๊ณ ๋ฅธ ์งํ›„์˜ Enter๊ฐ€ ๋ฐฉ๊ธˆ ๊ณ ๋ฅธ ํ•ญ๋ชฉ์„ ๋˜๋Œ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค (BUG-014). ์ €์žฅ ์ˆœ์„œ๋Š” ๊ณ ๋ฅธ ์ˆœ์„œ์ด๋ฉฐ, ์›๋ณธ์ด ๋ฐฐ์—ด์ด๋ฉด ๋ฐฐ์—ด๋กœ ยท ์ฝค๋งˆ ๋ฌธ์ž์—ด์ด๋ฉด ์ฝค๋งˆ ๋ฌธ์ž์—ด๋กœ ๋˜๋Œ๋ ค ์ปค๋ฐ‹ํ•ฉ๋‹ˆ๋‹ค.

Skills๋Š” ์ •์  ๋ชฉ๋ก ๊ฒ€์ƒ‰(editorSearch: true, ๊ฐ’์€ ๋ฐฐ์—ด), Regions๋Š” lazy ๊ฒ€์ƒ‰(fetch + 250ms ์ง€์—ฐ, ๊ฐ’์€ ์ฝค๋งˆ ๋ฌธ์ž์—ด)์ž…๋‹ˆ๋‹ค.

ํŒ์—… ํผ(popupEditor)์—์„œ๋Š” ์ ‘ํžˆ๋Š” ์ฝค๋ณด๋ฐ•์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค โ€” ํ‰์†Œ์—” ์นฉ ์ค„๊ณผ ๊ฒ€์ƒ‰์ฐฝ๋งŒ ๋ณด์ด๊ณ  ํด๋ฆญยทํƒ€์ดํ•‘ํ•  ๋•Œ๋งŒ ๋ชฉ๋ก์ด ๋– ์„œ ๋‹ค๋ฅธ ํ•„๋“œ๋ฅผ ๋ฎ์Šต๋‹ˆ๋‹ค. ๊ฒ€์ƒ‰์ด ์—†๋Š” ์ผ๋ฐ˜ multiselect๊ฐ€ ํผ์—์„œ ํ•ญ์ƒ ํŽผ์ณ์ง€๋Š” ์ด์œ ๋Š” "๊ณ ๋ฅธ ๊ฐ’์„ ๋ณด์—ฌ์ค„ ์ž๋ฆฌ๊ฐ€ ์—†์–ด์„œ"์ธ๋ฐ, ์นฉ ์ค„์ด ๊ทธ ์ž๋ฆฌ๋ฅผ ๋Œ€์‹ ํ•˜๋ฏ€๋กœ ์ ‘์–ด๋„ ์ •๋ณด๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ–‰์„ ๋”๋ธ”ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํผ์ด ์—ด๋ฆฝ๋‹ˆ๋‹ค. SkillsยทRegions ํ•„๋“œ๊ฐ€ ์นฉ ์ฝค๋ณด๋ฐ•์Šค์ž…๋‹ˆ๋‹ค.

Fill Handle (์—‘์…€์‹ ์ฑ„์šฐ๊ธฐ)

fillHandle: true(cellSelection ํ•„์š”)๋Š” ์„ ํƒ ๋ฒ”์œ„ ์šฐํ•˜๋‹จ์— ์ฑ„์šฐ๊ธฐ ํ•ธ๋“ค์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ํ•ธ๋“ค์„ ์„ธ๋กœ๋กœ ๋“œ๋ž˜๊ทธํ•˜๋ฉด ์ˆซ์ž 2๊ฐœ ์ด์ƒ์€ ๋“ฑ์ฐจ ์ˆ˜์—ด๋กœ ์™ธ์‚ฝํ•˜๊ณ (1, 3 โ†’ 5, 7, 9โ€ฆ), ๊ทธ ์™ธ์—๋Š” ํŒจํ„ด์„ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค. ํŽธ์ง‘ ๊ฐ€๋Šฅํ•œ ์…€์—๋งŒ ์“ฐ์ด๊ณ  validatorยท beforeCellSave๋ฅผ ํ†ต๊ณผํ•œ ๊ฐ’๋งŒ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.

Salary ์…€ ๋‘ ๊ฐœ๋ฅผ ์„ธ๋กœ๋กœ ๋“œ๋ž˜๊ทธํ•ด ์„ ํƒํ•œ ๋’ค, ํŒŒ๋ž€ ํ•ธ๋“ค์„ ์•„๋ž˜๋กœ ๋Œ์–ด ๋ณด์„ธ์š”.

ํผ ํŽธ์ง‘ Popup Editor

ํ–‰ ๋‹จ์œ„ ํผ ํŽธ์ง‘. ์ธ๋ผ์ธ ์—๋””ํ„ฐ์™€ ์ปฌ๋Ÿผ ์ •์˜๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

popupEditor๋Š” ์ธ๋ผ์ธ ์…€ ํŽธ์ง‘ ๋Œ€์‹  ํ–‰ ์ „์ฒด๋ฅผ ํผ์—์„œ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค. ํผ์˜ ๊ฐ ํ•„๋“œ๋Š” ์ปฌ๋Ÿผ ์ •์˜๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•˜๋ฏ€๋กœ editor ยท editorOptions ยท validator๊ฐ€ ์ธ๋ผ์ธ๊ณผ ๋˜‘๊ฐ™์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค โ€” ์•„๋ž˜ ์˜ˆ์ œ๋Š” ์ง€์›ํ•˜๋Š” ์—๋””ํ„ฐ ํ˜•์‹์„ ์ „๋ถ€ ํ•œ ํผ์— ๋‹ด์•˜์Šต๋‹ˆ๋‹ค: text ยท text+validator ยท number ยท date ยท datetime ยท select(๋ฌธ์ž์—ด) ยท select({ label, value }) ยท ๊ฒ€์ƒ‰ํ˜• select(์ •์ ) ยท ๊ฒ€์ƒ‰ํ˜• select(lazy fetch) ยท multiselect ยท radio ยท checkbox(๋ถˆ๋ฆฌ์–ธ) ยท checkbox(Y/N ๊ฐ’ ๋งคํ•‘) ยท ์ปค์Šคํ…€ ๊ฐ์ฒด ยท ์ฝ๊ธฐ ์ „์šฉ. ๊ฒ€์ฆ์— ์‹คํŒจํ•˜๋ฉด ๋ผ๋ฒจ์ด ๋นจ๊ฐ›๊ฒŒ ๋ฐ”๋€Œ๋ฉฐ ์ €์žฅ์ด ๋ง‰ํž™๋‹ˆ๋‹ค. ์œ„์น˜๋Š” 'center'(๊ธฐ๋ณธ) ยท 'left' ยท 'right'(์Šฌ๋ผ์ด๋“œ ํŒจ๋„), ๋ฐฐ์น˜๋Š” columns: 1 | 2 (ํญ์ด ๋ชจ์ž๋ผ๋ฉด ์ž๋™์œผ๋กœ 1์—ด์ด ๋˜๊ณ , ๋” ์ข์•„์ง€๋ฉด ๋ผ๋ฒจ์ด ์ž…๋ ฅ ์œ„๋กœ ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค). ํ–‰์„ ๋”๋ธ”ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ์•„๋ž˜ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๋ณด์„ธ์š”.

ํ–‰์„ ๋”๋ธ”ํด๋ฆญํ•˜๋ฉด ํŽธ์ง‘ ํผ์ด ์—ด๋ฆฝ๋‹ˆ๋‹ค.

ํผ ํ•˜๋‹จ ๋ฒ„ํŠผ์€ buttons ๋ฐฐ์—ด๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค โ€” ๋ฌธ์ž์—ด 'save'/'cancel'์€ ๋‚ด์žฅ ๋ฒ„ํŠผ์ด๊ณ , ๊ฐ์ฒด๋ฅผ ์„ž์–ด ๋ฐฐ์—ด ์ˆœ์„œ๋Œ€๋กœ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ปฌ๋Ÿผ๋งˆ๋‹ค column.popupEditor๋กœ ํŒ์—… ์•ˆ์—์„œ๋งŒ ๋ผ๋ฒจ ยท ๋„์›€๋ง ยท ์ˆœ์„œ ยท ์ฝ๊ธฐ ์ „์šฉ ยท span์„ ๋ฐ”๊พธ๊ฑฐ๋‚˜, ์—๋””ํ„ฐ๋ฅผ ํ†ต์งธ๋กœ ๊ต์ฒดํ•˜๊ณ (์…€์€ ์ข์œผ๋‹ˆ select, ํผ์€ ๋„“์œผ๋‹ˆ ๊ฒ€์ƒ‰ํ˜•), ํผ์—์„œ๋งŒ ๋‹ค๋ฅธ validator๋ฅผ ๊ฑธ๊ณ , ํ•„๋“œ ์˜† ๋ฒ„ํŠผ๊ณผ ์ž„์˜ HTML(before/after)์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๋“œ ์…€์˜ ํ‘œ์‹œยท๋™์ž‘์€ ์ „ํ˜€ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ์•„๋ž˜ ๊ทธ๋ฆฌ๋“œ์—์„œ ์…€์„ ์ง์ ‘ ๋ณด์„ธ์š”.

ํ–‰์„ ๋”๋ธ”ํด๋ฆญํ•˜๋ฉด ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆ๋œ ํผ์ด ์—ด๋ฆฝ๋‹ˆ๋‹ค.

ํŒ์—… ๋ฒ„ํŠผ์˜ onLoad๋Š” ํผ์ด ์™„์ „ํžˆ ๋งŒ๋“ค์–ด์ง„ ์งํ›„ ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค โ€” onClick๊ณผ ๊ฐ™์€ ์ปจํ…์ŠคํŠธ์— ๋ฒ„ํŠผ DOM(ctx.buttonEl)์ด ๋”ํ•ด์ ธ, ํ–‰ ๊ฐ’์„ ๋ณด๊ณ  ๋ฒ„ํŠผ ๋ฌธ๊ตฌยท์ž ๊ธˆ์„ ์ •ํ•˜๊ฑฐ๋‚˜ ํ•ด๋‹น ํ•„๋“œ(ctx.fieldEl)์™€ ๊ฐ’(ctx.setValue)์„ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธ์ถœ ์ˆœ์„œ๋Š” DOM ์ˆœ์„œ(ํ•„๋“œ ๋ฒ„ํŠผ โ†’ ํ‘ธํ„ฐ ๋ฒ„ํŠผ)์ด๊ณ , ๋ชจ๋“  ํ•„๋“œ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•˜๋ฏ€๋กœ ๋‹ค๋ฅธ ํ•„๋“œ๋„ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ–‰์„ ๋”๋ธ”ํด๋ฆญํ•˜๋ฉด onLoad ํ˜ธ์ถœ ์ˆœ์„œ๊ฐ€ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ยท CRUD Data & CRUD

ํ–‰ ์ถ”๊ฐ€ยท์ˆ˜์ •ยท์‚ญ์ œ์™€ ๋ณ€๊ฒฝ ์ถ”์ . ์ €์žฅ ์ „ ์Šคํ…Œ์ด์ง• ์ƒํƒœ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

Row Data API (CRUD)

setRowData ยท addRow ยท updateRow(row, changes) ยท removeRows๋กœ ํ–‰์„ ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑํ•˜๊ฒŒ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. getRowId ์˜ต์…˜์€ ํ–‰ ์‹๋ณ„ ๊ธฐ์ค€์„ ์ง€์ •ํ•˜๊ณ , getRowData()๋Š” ์ „์ฒด ๋ฐ์ดํ„ฐ, getDisplayedRows()/ getDisplayedRowCount()๋Š” ํ•„ํ„ฐยท์ •๋ ฌ์ด ์ ์šฉ๋œ ํ‘œ์‹œ ๋ทฐ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค.

ํ–‰์„ ์„ ํƒํ•˜๊ณ  ๋ฒ„ํŠผ์œผ๋กœ ์ถ”๊ฐ€/์ˆ˜์ •/์‚ญ์ œํ•ด ๋ณด์„ธ์š”.

Insert Position (addRow / addRows index)

addRow(row, index) / addRows(rows, index)์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ์‚ฝ์ž… ์œ„์น˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค โ€” 0์ด๋ฉด ๋งจ ์•ž, ์ƒ๋žตํ•˜๋ฉด ๊ธฐ์กด์ฒ˜๋Ÿผ ๋งจ ๋’ค. ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ํด๋žจํ”„๋ฉ๋‹ˆ๋‹ค. index๋Š” ์›๋ณธ ๋ฐฐ์—ด ๊ธฐ์ค€์ด๋ผ ์ •๋ ฌ์ด ์ผœ์ ธ ์žˆ์œผ๋ฉด ํ‘œ์‹œ ์ˆœ์„œ๋Š” ์ •๋ ฌ์ด ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. rowNumbers๋กœ ์‚ฝ์ž… ์œ„์น˜๋ฅผ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

๋ฒ„ํŠผ์œผ๋กœ ํ–‰์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ–‰ ๋ฒˆํ˜ธ ์ปฌ๋Ÿผ์—์„œ ์‚ฝ์ž… ์œ„์น˜๊ฐ€ ๋ณด์ž…๋‹ˆ๋‹ค.

Change Tracking & Undo / Redo

trackChanges: true๋Š” ๋งˆ์ง€๋ง‰ ๊ธฐ์ค€์„  ์ดํ›„์˜ ๋ณ€๊ฒฝ์„ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค โ€” ์ˆ˜์ • ์…€์€ ๋ชจ์„œ๋ฆฌ ๋งˆ์ปค(dirty), ์ถ”๊ฐ€ ํ–‰์€ ๋ฐฐ๊ฒฝ์œผ๋กœ ํ‘œ์‹œ๋˜๊ณ  getChanges() / commitChanges() / rollbackChanges()๋กœ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. undoRedo: true๋Š” Ctrl+Z / Ctrl+Y์™€ undo() / redo()๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

์…€์„ ๋”๋ธ”ํด๋ฆญํ•ด ์ˆ˜์ •ํ•ด ๋ณด์„ธ์š” โ€” ์ˆ˜์ •๋œ ์…€์— ์ฃผํ™ฉ ๋งˆ์ปค๊ฐ€ ์ƒ๊ธฐ๊ณ  undo๋กœ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Built-in CRUD Staging (statusColumn / softDelete)

์œ„ ์นด๋“œ์˜ ์Šคํ…Œ์ด์ง• ํŒจํ„ด์„ ์˜ต์…˜ ๋‘ ๊ฐœ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค โ€” ์ƒํƒœ ๊ด€๋ฆฌ ์ฝ”๋“œ๊ฐ€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค. statusColumn์€ ๋ณ€๊ฒฝ ์ถ”์  ์ƒํƒœ(added/updated/deleted)๋ฅผ ํƒœ๊ทธ ์ปฌ๋Ÿผ์œผ๋กœ ํ‘œ์‹œํ•˜๊ณ , softDelete: true๋Š” ์‚ญ์ œ๋ฅผ ์Šคํ…Œ์ด์ง•์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค: ์„œ๋ฒ„ ํ–‰์€ ์‚ญ์ œ ํ‘œ์‹œ(์ทจ์†Œ์„ , ํŽธ์ง‘ ์ฐจ๋‹จ, restoreRows()๋กœ ๋ณต์›), ์‹ ๊ทœ ํ–‰์€ ๋กœ์šฐ ์ž์ฒด ์ œ๊ฑฐ. ์…€์„ ๋”๋ธ”ํด๋ฆญํ•ด ํŽธ์ง‘ํ•˜๋ฉด ์ž๋™์œผ๋กœ ‘์ˆ˜์ •’์ด ๋˜๊ณ , commitChanges()(์ €์žฅ ์„ฑ๊ณต ํ›„ โ€” ์‚ญ์ œ ํ‘œ์‹œ ํ–‰ ๋ฌผ๋ฆฌ ์ œ๊ฑฐ) / rollbackChanges()(์ „๋ถ€ ๋˜๋Œ๋ฆฌ๊ธฐ)๋กœ ๋งˆ๋ฌด๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์ค‘โ€ฆ ์ด๋ฆ„/๊ธ‰์—ฌ ์…€์„ ๋”๋ธ”ํด๋ฆญํ•ด ํŽธ์ง‘ํ•ด ๋ณด์„ธ์š”.

๊ทธ๋ฃนํ•‘ ยท ํŠธ๋ฆฌ Grouping & Tree

ํ–‰์„ ๊ณ„์ธต์œผ๋กœ ๋ฌถ๋Š” ์„ธ ๊ฐ€์ง€ ๋ฐฉ์‹ โ€” ๊ทธ๋ฃนํ•‘, ํŠธ๋ฆฌ, ๋งˆ์Šคํ„ฐ-๋””ํ…Œ์ผ.

Row Grouping & Aggregation

groupBy: ['department']๋กœ ํ–‰์„ ๊ทธ๋ฃนํ•‘ํ•˜๊ณ , ๊ทธ๋ฃน ํ—ค๋” ํ–‰์„ ํด๋ฆญ(๋˜๋Š” Enter)ํ•ด ์ ‘๊ณ  ํŽผ์นฉ๋‹ˆ๋‹ค. aggFunc: 'sum' | 'avg' | 'min' | 'max' | 'count'๋ฅผ ์ปฌ๋Ÿผ์— ์ง€์ •ํ•˜๋ฉด ๊ทธ๋ฃน ํ—ค๋”์™€ grandTotal ์š”์•ฝ ํ–‰์— ์ง‘๊ณ„๊ฐ’์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋‹จ๊ณ„ ๊ทธ๋ฃนํ•‘(['department', 'city'])๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฃน ํ—ค๋” ํ–‰์„ ํด๋ฆญํ•ด ์ ‘๊ณ  ํŽผ์ณ ๋ณด์„ธ์š”.

Custom aggFunc (์ง‘๊ณ„ ํ•จ์ˆ˜ ์ง์ ‘ ์ž‘์„ฑ)

aggFunc์— ๋ฌธ์ž์—ด ๋Œ€์‹  (values, ctx) => any ํ•จ์ˆ˜๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. values๋Š” ๊ทธ ์ปฌ๋Ÿผ์˜ ์›๋ณธ ๊ฐ’ ๋ฐฐ์—ด, ctx๋Š” { rows, field, colDef, parent }์ด๊ณ  parent๋Š” ํŠธ๋ฆฌ ์š”์•ฝ์—์„œ๋งŒ ๋ถ€๋ชจ ํ–‰์ž…๋‹ˆ๋‹ค(๊ทธ๋ฃนยท์ „์ฒดํ•ฉ๊ณ„์—์„œ๋Š” null). ์ง‘๊ณ„๋Š” ํ•„ํ„ฐ ์ ์šฉ ํ›„์˜ ํ–‰์œผ๋กœ ๋งค๋ฒˆ ๋‹ค์‹œ ๊ณ„์‚ฐ๋˜๋ฏ€๋กœ, ์•„๋ž˜ Name ์ปฌ๋Ÿผ์˜ (์ž์† ์ˆ˜)๋Š” ํ•„ํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ๋”ฐ๋ผ๊ฐ‘๋‹ˆ๋‹ค. ์ปค์Šคํ…€ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ์—๋Š” valueFormatter๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ํ•จ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ถœ๋ ฅ์„ ์ •ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํด๋” ์ด๋ฆ„ ์˜† (n)์€ ์ž์† ํŒŒ์ผ ์ˆ˜, Size๋Š” ์ค‘์•™๊ฐ’์ž…๋‹ˆ๋‹ค.

Tree Grid (treeData)

treeData๋Š” ๊ณ„์ธต ๋ฐ์ดํ„ฐ๋ฅผ ํŠธ๋ฆฌ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค โ€” nested(children ๋ฐฐ์—ด)์™€ flat(parentId) ํ˜•์‹์„ ๋ชจ๋‘ ์ง€์›ํ•˜๊ณ , ์ •๋ ฌ์€ ํ˜•์ œ๋ผ๋ฆฌ, ํ•„ํ„ฐ๋Š” ๋งค์น˜๋œ ๋…ธ๋“œ์˜ ์กฐ์ƒ์„ ์œ ์ง€ํ•œ ์ฑ„ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. expandAllNodes()/collapseAllNodes()/toggleNode()๋กœ ํ”„๋กœ๊ทธ๋žจ ์ œ์–ด, beforeNodeToggle(์ทจ์†Œ ๊ฐ€๋Šฅ)/nodeExpanded/nodeCollapsed ์ด๋ฒคํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํด๋” ํ–‰์˜ ํ™”์‚ดํ‘œ๋ฅผ ํด๋ฆญํ•ด ํŽผ์น˜๊ณ  ์ ‘์–ด ๋ณด์„ธ์š”.

Tree Checkbox โ€” cascade (checkboxSelection)

ํŠธ๋ฆฌ ๋ชจ๋“œ์—์„œ๋Š” ๊ธฐ์กด checkboxSelection ์ปฌ๋Ÿผ์ด 3์ƒํƒœ ์บ์Šค์ผ€์ด๋“œ ์ฒดํฌ๋ฐ•์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค โ€” ๋ถ€๋ชจ๋ฅผ ์ฒดํฌํ•˜๋ฉด ์ž์† ์ „์ฒด๊ฐ€ ํ–‰ ์„ ํƒ๋˜๊ณ , ์ž์‹ ์ผ๋ถ€๋งŒ ์„ ํƒ๋˜๋ฉด ๋ถ€๋ชจ๊ฐ€ indeterminate๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค (treeData.cascade: false๋กœ ๋Œ ์ˆ˜ ์žˆ์Œ). ๋ณ„๋„ API ์—†์ด ์„ ํƒ API๋ฅผ ๊ทธ๋Œ€๋กœ ์”๋‹ˆ๋‹ค: getSelectedRows()ยท selectAll()/deselectAll()ยทselectionChanged/beforeSelectionChange. headerCheckboxSelection์˜ ํ—ค๋” ์ฒดํฌ๋ฐ•์Šค๋„ ํŠธ๋ฆฌ ๊ทœ์น™์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค โ€” ์ „์ฒด ์ฒดํฌ/ํ•ด์ œ ์‹œ treeData.checkboxDisabled(row) ํ–‰์€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ , ํ‘œ์‹œ ์ƒํƒœ(์ „์ฒด/์ผ๋ถ€)๋„ ์ฒดํฌ ๊ฐ€๋Šฅํ•œ ํ–‰๋งŒ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ์นด๋“œ๋Š” flat(parentId) ํ˜•์‹ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํด๋”๋ฅผ ์ฒดํฌํ•ด ๋ณด์„ธ์š” โ€” ์ž์† ์ „์ฒด๊ฐ€ ํ–‰ ์„ ํƒ๋˜๊ณ , license ํŒŒ์ผ์€ ๋น„ํ™œ์„ฑ์ž…๋‹ˆ๋‹ค.

Tree Summary (treeData.summary)

treeData.summary: true๋Š” column.aggFunc๊ฐ€ ์ง€์ •๋œ ์ปฌ๋Ÿผ์—์„œ ๋ถ€๋ชจ ๋…ธ๋“œ ํ–‰์— ์ž์† ๋ฆฌํ”„๋“ค์˜ ์ง‘๊ณ„๊ฐ’์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค (ํ‘œ์‹œ ์ „์šฉ โ€” ๋ฐ์ดํ„ฐ๋Š” ๊ทธ๋Œ€๋กœ). ํ•„ํ„ฐ๋ฅผ ๊ฑธ๋ฉด ๋‚จ์€ ๋ฆฌํ”„ ๊ธฐ์ค€์œผ๋กœ ์ง‘๊ณ„๊ฐ€ ๋‹ค์‹œ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

ํด๋” ํ–‰์˜ Size ์ปฌ๋Ÿผ์— ์ž์† ํŒŒ์ผ ํฌ๊ธฐ ํ•ฉ๊ณ„๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Tree Lazy Loading (treeData.fetchChildren)

treeData.fetchChildren(row)๋Š” ๋…ธ๋“œ๋ฅผ ์ฒ˜์Œ ํŽผ์น  ๋•Œ ์ž์‹์„ ๋น„๋™๊ธฐ๋กœ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค (Promise ๋ฐ˜ํ™˜, ๋กœ๋”ฉ ์ค‘ ํ† ๊ธ€์ด ์Šคํ”ผ๋„ˆ๋กœ ํšŒ์ „). hasChildren(row)๊ฐ€ ๋กœ๋“œ ์ „ ํ† ๊ธ€ ํ‘œ์‹œ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๊ณ , ๋นˆ ๋ฐฐ์—ด์ด ์˜ค๋ฉด ๋ฆฌํ”„๋กœ ํ™•์ •๋ฉ๋‹ˆ๋‹ค. ์‹คํŒจ ์‹œ dataLoadError๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์ ‘ํžŒ ์ƒํƒœ๋กœ ๋‚จ์•„ ์žฌ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋”๋ฅผ ํŽผ์น˜๋ฉด 500ms ์ง€์—ฐ ํ›„ ์ž์‹์ด ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค (๊ฐ™์€ ๋…ธ๋“œ๋Š” 1ํšŒ๋งŒ).

Master-Detail Rows

rowDetail: { renderer(row), height }๋Š” ํ–‰ ์•„๋ž˜์— ์ปค์Šคํ…€ ๋””ํ…Œ์ผ ํŒจ๋„์„ ํŽผ์นฉ๋‹ˆ๋‹ค. ์ฒซ ์ปฌ๋Ÿผ์˜ ์…ฐ๋ธŒ๋ก (์ž๋™ ์ถ”๊ฐ€)์ด๋‚˜ expandRow(row) / collapseRow(row) / toggleRowDetail(row)๋กœ ์ œ์–ดํ•˜๊ณ  rowExpanded / rowCollapsed ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋””ํ…Œ์ผ ๋†’์ด๋Š” ๊ฐ€์ƒ ์Šคํฌ๋กค ๋ ˆ์ด์•„์›ƒ์— ์ •ํ™•ํžˆ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. (renderer ๋ฐ˜ํ™˜ HTML์€ ์ด์Šค์ผ€์ดํ”„๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋งˆํฌ์—…๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”.)

ํ–‰ ์•ž์˜ โ–ธ ๋ฅผ ํด๋ฆญํ•ด ๋””ํ…Œ์ผ ํŒจ๋„์„ ํŽผ์ณ ๋ณด์„ธ์š”.

์›๊ฒฉ ๋ฐ์ดํ„ฐ Remote Data

์„œ๋ฒ„์—์„œ ์กฐํšŒํ•˜๋Š” ๊ทธ๋ฆฌ๋“œ โ€” ์„œ๋ฒ„ ์ •๋ ฌยทํ•„ํ„ฐยทํŽ˜์ด์ง•๊ณผ ๋ฌดํ•œ ์Šคํฌ๋กค.

Remote Data Source (Server-side Sort / Filter / Paging)

dataSource: { url, method, params, parse }๋Š” fetch๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. sortMode / filterMode / pageMode: 'server'์ธ ์ถ•์€ ํด๋ผ์ด์–ธํŠธ ์ฒ˜๋ฆฌ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ(pageยทpageSizeยทsortยทfilterยทquickFilter)๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. reloadData()๋กœ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. ์ด ๋ฐ๋ชจ๋Š” ๋ฐ๋ชจ ์„œ๋ฒ„์˜ /api/employees(500ํ–‰)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ—ค๋”๋ฅผ ํด๋ฆญํ•˜๋ฉด ์ •๋ ฌ์„ ์„œ๋ฒ„๊ฐ€ ์ˆ˜ํ–‰ํ•˜๊ณ , ํŽ˜์ด์ง€๋ฅผ ๋„˜๊ธฐ๋ฉด ํ•ด๋‹น ํŽ˜์ด์ง€๋งŒ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค.

Remote Data Source โ€” ์„œ๋ฒ„ ์ŠคํŽ™ ๋งž์ถค (request / parse / headers)

์„œ๋ฒ„์˜ ํŒŒ๋ผ๋ฏธํ„ฐยท์‘๋‹ต ์ŠคํŽ™์ด ๊ทธ๋ฆฌ๋“œ ๊ธฐ๋ณธ๊ฐ’๊ณผ ๋‹ค๋ฅผ ๋•Œ: dataSource.request(state)๋กœ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„œ๋ฒ„ ์ŠคํŽ™(์˜ˆ: offset/limit/orderBy)์œผ๋กœ ๋ฐ”๊พธ๊ณ , parse(json)์œผ๋กœ envelope ์‘๋‹ต์„ { rows, total }๋กœ ๋ณ€ํ™˜ํ•˜๋ฉฐ, headers๋กœ ์ธ์ฆ ํ† ํฐ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์กฐํšŒ ์กฐ๊ฑด์€ params ํ•จ์ˆ˜ + reloadData()๋กœ, ์„œ๋ฒ„ ๊ต์ฒด๋Š” setDataSource()๋กœ. ์ด ๋ฐ๋ชจ๋Š” ๋ฐ๋ชจ ์„œ๋ฒ„์˜ /api/employees-v2(๋‹ค๋ฅธ ์ŠคํŽ™์˜ ์„œ๋ฒ„ ํ‰๋‚ด)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ—ค๋” ์ •๋ ฌยทํŽ˜์ด์ง€ ์ด๋™์ด offset/limit/orderBy ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋„คํŠธ์›Œํฌ ํƒญ์—์„œ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

Nested Request Params (์ค‘์ฒฉ ํŒŒ๋ผ๋ฏธํ„ฐ ์ง๋ ฌํ™”)

dataSource.request๊ฐ€ ์ค‘์ฒฉ ๊ฐ์ฒดยท๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ด๋„ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์œผ๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŽผ์ณ์ง‘๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์˜ ์ค‘์ฒฉ ํ‘œ๊ธฐ๋Š” ํ‘œ์ค€์ด ์—†์–ด ์„œ๋ฒ„๋งˆ๋‹ค ๊ด€๋ก€๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ dataSource.paramsFormat์œผ๋กœ ๋งž์ถฅ๋‹ˆ๋‹ค โ€” 'dot'(๊ธฐ๋ณธ, SpringยทASP.NET)์€ page.selectPage=1, 'bracket'(qsยทPHPยทRails)์€ page[selectPage]=1. ๋ฐฐ์—ด ์ธ๋ฑ์Šค๋Š” ๋‘ ํ‘œ๊ธฐ ๋ชจ๋‘ ๋Œ€๊ด„ํ˜ธ์ž…๋‹ˆ๋‹ค(sorts[0].field โ€” Spring์˜ List ๋ฐ”์ธ๋”ฉ ๊ทœ์•ฝ). ๋‘˜ ๋‹ค ์•„๋‹ˆ๋ฉด paramsSerializer๋กœ ์ง๋ ฌํ™”๋ฅผ ํ†ต์งธ๋กœ ๋Œ€์ฒดํ•˜์„ธ์š”. ์•„๋ž˜ ์…€๋ ‰ํŠธ๋กœ ๋ฐ”๊ฟ” ๋ณด๋ฉด status line์— ๋ฐ๋ชจ ์„œ๋ฒ„๊ฐ€ ์‹ค์ œ๋กœ ๋ณต์›ํ•œ ๊ตฌ์กฐ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค (์ด ์นด๋“œ๋Š” ๋ฐ๋ชจ ์„œ๋ฒ„๊ฐ€ ์žˆ์–ด์•ผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค โ€” ๋กœ์ปฌ์—์„œ๋Š” node demo/server.js 8087).

ํ—ค๋”๋ฅผ ํด๋ฆญํ•ด ์ •๋ ฌํ•˜๊ฑฐ๋‚˜ ํŽ˜์ด์ง€๋ฅผ ๋„˜๊ธฐ๋ฉด ์„œ๋ฒ„๊ฐ€ ๋ฐ›์€ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Deferred First Load (dataSource.autoLoad)

dataSource.autoLoad: false๋ฉด ๊ทธ๋ฆฌ๋“œ๊ฐ€ ์Šค์Šค๋กœ ์ฒซ ์กฐํšŒ๋ฅผ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (๊ธฐ๋ณธ๊ฐ’ true). ๊ฒ€์ƒ‰ ์กฐ๊ฑด์„ ๋ฐ›์€ ๋’ค์— ์กฐํšŒํ•˜๋Š” ํ™”๋ฉด, ๋น„์‹ผ ์ฟผ๋ฆฌ, ํƒญ์ด ์—ด๋ฆด ๋•Œ๊นŒ์ง€ ๋ฏธ๋ฃจ๋Š” ๊ฒฝ์šฐ์— ์”๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๋„๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ "์ž๋™"๋งŒ ๋„๋Š” ๊ฒƒ์ด๋ผ reloadData() ยท loadMore() ๊ฐ™์€ ๋ช…์‹œ์  ํ˜ธ์ถœ์€ ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•˜๊ณ , ์ •๋ ฌยทํ•„ํ„ฐ ์ž๋™ ์žฌ์กฐํšŒ๋„ ํ•œ ๋ฒˆ์ด๋ผ๋„ ์กฐํšŒํ•œ ๋’ค๋ถ€ํ„ฐ๋Š” ํ‰์†Œ์ฒ˜๋Ÿผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. setDataSource()๋„ ์ƒˆ ์†Œ์Šค๊ฐ€ autoLoad: false๋ฉด ๊ต์ฒด๋งŒ ํ•˜๊ณ  ์กฐํšŒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์•„์ง ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค โ€” ๋ถ€์„œ๋ช…์„ ๋„ฃ๊ณ  ์กฐํšŒ๋ฅผ ๋ˆ„๋ฅด์„ธ์š”. (๋„คํŠธ์›Œํฌ ํƒญ์— ์š”์ฒญ์ด ์—†์Šต๋‹ˆ๋‹ค)

Infinite Scroll (infiniteScroll)

infiniteScroll: true | { threshold, pageSize }๋Š” ๋ฐ”๋‹ฅ ๊ทผ์ฒ˜์— ๋‹ฟ์œผ๋ฉด ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ์ž๋™์œผ๋กœ ์กฐํšŒํ•ด ๊ธฐ์กด ํ–‰ ๋’ค์— ์ด์–ด ๋ถ™์ž…๋‹ˆ๋‹ค(๊ต์ฒด๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค). dataSource๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ํŽ˜์ด์ € UI์™€๋Š” ๋ฐฐํƒ€์ž…๋‹ˆ๋‹ค โ€” ๋Œ€์‹  ํ•˜๋‹จ ์ƒํƒœ ๋ฐ”๊ฐ€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘ / N๊ฑด ๋ถˆ๋Ÿฌ์˜ด / ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€๋ฅผ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ๋ ํŒ์ •์€ ์„œ๋ฒ„๊ฐ€ ์ค€ ํ”Œ๋ž˜๊ทธ(last ยท lastPage ยท isLast ยท hasMore ยท hasNext)๊ฐ€ ์ตœ์šฐ์„ ์ด๊ณ , ์—†์œผ๋ฉด total โ†’ ์ˆ˜์‹  ๊ฑด์ˆ˜ ์ˆœ์œผ๋กœ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐ๋ชจ ์„œ๋ฒ„(/api/employees-infinite)๋Š” ์ด๊ฑด์ˆ˜๋ฅผ ์ฃผ์ง€ ์•Š๊ณ  last๋งŒ ์ฃผ๋ฏ€๋กœ, ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€ ํ‘œ์‹œ๊ฐ€ ์ˆœ์ „ํžˆ ๊ทธ ํ”Œ๋ž˜๊ทธ์—์„œ ๋‚˜์˜ต๋‹ˆ๋‹ค. ์ƒํƒœ ๋ฐ” ์™ผ์ชฝ์˜ ํฌ๊ธฐ ์„ ํƒ์œผ๋กœ ํ•œ ๋ฒˆ์— ๋ฐ›์„ ํ–‰ ์ˆ˜๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (paginationPageSizeOptions๊ฐ€ ์„ ํƒ์ง€, ๋ฐ”๊พธ๋ฉด ์Œ“์ธ ๊ฒƒ์„ ๋ฒ„๋ฆฌ๊ณ  ์ƒˆ ํฌ๊ธฐ๋กœ ๋‹ค์‹œ ๋ฐ›์Šต๋‹ˆ๋‹ค). ๋„๋ ค๋ฉด infiniteScroll: { pageSizeSelector: false }.

์•„๋ž˜๋กœ ์Šคํฌ๋กคํ•˜๋ฉด 25ํ–‰์”ฉ ์ž๋™์œผ๋กœ ์ด์–ด ๋ฐ›์Šต๋‹ˆ๋‹ค.

Remote Data + CRUD Staging (์‹ ๊ทœ / ์ˆ˜์ • / ์‚ญ์ œ ์ƒํƒœ ์ปฌ๋Ÿผ)

์„œ๋ฒ„์—์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ์ปฌ์—์„œ ํŽธ์ง‘ํ•ด ๋‘์—ˆ๋‹ค๊ฐ€ ํ•œ ๋ฒˆ์— ์ €์žฅํ•˜๋Š” ์‹ค๋ฌด ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์ƒํƒœ ์ปฌ๋Ÿผ(_rowStatus)์„ renderers.tag๋กœ ํ‘œ์‹œํ•˜๊ณ  โ€” ์‹ ๊ทœ๋Š” addRow๋กœ ์ถ”๊ฐ€๋œ ๋กœ์ปฌ ํ–‰, ์ˆ˜์ •์€ ์„œ๋ฒ„ ํ–‰์„ ํŽธ์ง‘(rowValueChanged)ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ • ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ ํ–‰, ์‚ญ์ œ๋Š” ์„œ๋ฒ„ ํ–‰์— ์‚ญ์ œ ํ‘œ์‹œ(getRowClass๋กœ ์ทจ์†Œ์„ ). ์‹ ๊ทœ ํ–‰์„ ์‚ญ์ œํ•˜๋ฉด ์„œ๋ฒ„์— ์—†๋Š” ๋ฐ์ดํ„ฐ์ด๋ฏ€๋กœ ๋กœ์šฐ ์ž์ฒด๊ฐ€ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค(removeRows). ์‚ญ์ œ ํ‘œ์‹œ๋œ ํ–‰์€ beforeCellSave๋กœ ํŽธ์ง‘์ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค. v2.6๋ถ€ํ„ฐ๋Š” ์ด ํŒจํ„ด์ด statusColumn / softDelete ์˜ต์…˜์œผ๋กœ ๋‚ด์žฅ๋˜์–ด ์•„๋ž˜ Built-in CRUD Staging ์นด๋“œ์ฒ˜๋Ÿผ ์†Œ๋น„์ž ์ฝ”๋“œ ์—†์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค โ€” ์ด ์นด๋“œ๋Š” ์˜ต์…˜ ์—†์ด ์ง์ ‘ ๊ตฌํ˜„ํ•  ๋•Œ์˜ ๋ ˆ์‹œํ”ผ๋กœ ๋‚จ๊ฒจ๋‘ก๋‹ˆ๋‹ค.

์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์ค‘โ€ฆ ์ด๋ฆ„/๊ธ‰์—ฌ ์…€์€ ๋”๋ธ”ํด๋ฆญ์œผ๋กœ ์ง์ ‘ ํŽธ์ง‘ํ•ด๋„ ‘์ˆ˜์ •’์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„์‚ฌ์ด๋“œ row model (Server-Side Row Model)

groupMode: 'server'๋Š” ๊ทธ๋ฃน ๊ณ„์ธต์„ ์„œ๋ฒ„๊ฐ€ ๊ณ„์‚ฐํ•˜๊ฒŒ ํ•˜๊ณ , ๊ทธ๋ฆฌ๋“œ๋Š” ํŽผ์นœ ๊ฒฝ๋กœ์˜ ๋ธ”๋ก๋งŒ ๋ฐ›์•„์˜จ๋‹ค. ์š”์ฒญ์—๋Š” groupBy(๊ทธ๋ฃน ์ถ•)์™€ groupKeys(์ง€๊ธˆ ํŽผ์นœ ๋…ธ๋“œ์˜ ์ƒ์œ„ ๊ฐ’)๊ฐ€ ์‹ค๋ฆฌ๊ณ , ํ‚ค๊ฐ€ ๋‹ค ์ฑ„์›Œ์ง€๋ฉด ์„œ๋ฒ„๊ฐ€ ๋ฆฌํ”„ ํ–‰์„ ์ค€๋‹ค. ๋ธ”๋ก์€ dataSource.blockSize ๋‹จ์œ„๋กœ ์ž˜๋ ค ์˜ค๊ณ  ๋‚จ์€ ๊ฒƒ์€ ‘๋” ๋ณด๊ธฐ’ ํ–‰์œผ๋กœ ์ด์–ด ๋ฐ›๋Š”๋‹ค. ์•„๋ž˜ ๋ฐ๋ชจ์˜ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ์…‹์€ 50,000ํ–‰์ด์ง€๋งŒ ๊ทธ๋ฆฌ๋“œ๊ฐ€ ํ•œ ๋ฒˆ์— ๋“ค๊ณ  ์žˆ๋Š” ๊ฒƒ์€ ๋ธ”๋ก ๋ช‡ ๊ฐœ๋ฟ์ด๋‹ค.

๋ฃจํŠธ ๋ธ”๋ก์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘โ€ฆ

ํด๋ฆฝ๋ณด๋“œ ยท ๋‚ด๋ณด๋‚ด๊ธฐ Clipboard & Export

์—‘์…€๊ณผ ๊ฐ’์„ ์ฃผ๊ณ ๋ฐ›๋Š” ๊ฒฝ๋กœ โ€” ๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ๊ธฐ, CSVยทExcelยทJSON ๋‚ด๋ณด๋‚ด๊ธฐ.

Clipboard Copy & Paste (TSV)

์„ ํƒํ•œ ํ–‰์„ Ctrl+C๋กœ ์—‘์…€ ํ˜ธํ™˜ TSV๋กœ ๋ณต์‚ฌํ•˜๊ณ (์„ ํƒ์ด ์—†์œผ๋ฉด ํฌ์ปค์Šค ์…€), ํฌ์ปค์Šค ์…€์„ ์‹œ์ž‘์ ์œผ๋กœ Ctrl+V๋กœ ๋ถ™์—ฌ๋„ฃ์Šต๋‹ˆ๋‹ค โ€” ํŽธ์ง‘ ๊ฐ€๋Šฅํ•œ ์…€์—๋งŒ ์“ฐ์ด๊ณ  validatorยทbeforeCellSave๋ฅผ ํ†ต๊ณผํ•œ ๊ฐ’๋งŒ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. column.suppressCopy๋กœ ๋ณต์‚ฌ์—์„œ ์ œ์™ธํ•  ์ปฌ๋Ÿผ์„ ์ง€์ •ํ•˜๊ณ , copy() / pasteTsv(text)๋กœ ์ฝ”๋“œ์—์„œ๋„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

ํ–‰์„ ์„ ํƒํ•ด Ctrl+C, ์…€์„ ํด๋ฆญํ•ด ํฌ์ปค์Šคํ•œ ๋’ค Ctrl+V โ€” Email์€ suppressCopy๋ผ ๋ณต์‚ฌ์—์„œ ๋น ์ง‘๋‹ˆ๋‹ค.

Cell / Block Selection & Find

cellSelection: true๋Š” ์…€ ํด๋ฆญยท๋“œ๋ž˜๊ทธยทShift+ํด๋ฆญ/ํ™”์‚ดํ‘œ๋กœ ๋ธ”๋ก ๋ฒ”์œ„๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค โ€” Ctrl+C๋Š” ๋ฒ”์œ„๋ฅผ ๊ทธ๋Œ€๋กœ TSV๋กœ ๋ณต์‚ฌํ•˜๊ณ  getCellRange()๋กœ ๋ฒ”์œ„๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. findNext(text)๋Š” ๋ทฐ์—์„œ ๋‹ค์Œ ๋งค์น˜๋ฅผ ์ฐพ์•„ ํฌ์ปค์Šคํ•˜๊ณ (๋์—์„œ ์ฒ˜์Œ์œผ๋กœ ์ˆœํ™˜), cellContextMenu / headerClicked / cellKeyDown ์ด๋ฒคํŠธ๋กœ ์ƒํ˜ธ์ž‘์šฉ์„ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.

์…€์„ ๋“œ๋ž˜๊ทธํ•ด ๋ธ”๋ก์„ ์„ ํƒํ•˜๊ณ  Ctrl+C๋กœ ๋ณต์‚ฌํ•ด ๋ณด์„ธ์š”. ์šฐํด๋ฆญ์€ cellContextMenu ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

CSV Export

ํ•„ํ„ฐยท์ •๋ ฌ์ด ์ ์šฉ๋œ ํ˜„์žฌ ๋ทฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค(ํฌ๋งคํ„ฐ ์ ์šฉ, RFC 4180 ์ด์Šค์ผ€์ดํ”„).

Excel Export & beforeExport

exportExcel(filename, sheetName)์€ ์˜์กด์„ฑ ์—†์ด ์ง„์งœ .xlsx ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค (๋ฌด์••์ถ• ZIP + SpreadsheetML โ€” ํฌ๋งคํ„ฐ ์—†๋Š” ์ˆซ์ž๋Š” ์ˆซ์ž ์…€๋กœ ๋‚˜๊ฐ€ ์—‘์…€์—์„œ ๋ฐ”๋กœ ๊ณ„์‚ฐ ๊ฐ€๋Šฅ). beforeExport ์ด๋ฒคํŠธ๋กœ ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ์ทจ์†Œํ•˜๊ฑฐ๋‚˜ rows/columns/filename์„ ๊ฐ€๊ณตํ•˜๊ณ , column.exportFormatter๋Š” ํ™”๋ฉด ํ‘œ์‹œ์™€ ๋‹ค๋ฅธ ๋‚ด๋ณด๋‚ด๊ธฐ ์ „์šฉ ํฌ๋งท์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

Salary๋Š” ํ™”๋ฉด์—์„  $ ํฌ๋งท, ์—‘์…€๋กœ๋Š” ์ˆซ์ž ๊ทธ๋Œ€๋กœ(exportFormatter) ๋‚˜๊ฐ‘๋‹ˆ๋‹ค.

Styled Excel Export (์Šคํƒ€์ผยท๋ณ‘ํ•ฉ ํฌํ•จ)

exportExcel()์ด ๊ธฐ๋ณธ์œผ๋กœ "๊ทธ๋ฆฌ๋“œ์—์„œ ๋ณด์ด๋Š” ๋Œ€๋กœ" ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค โ€” ํ—ค๋” ์Šคํƒ€์ผ, ๋‹ค๋‹จ ๊ทธ๋ฃน ํ—ค๋” ๋ณ‘ํ•ฉ, mergeCells ์„ธ๋กœ ๋ณ‘ํ•ฉ, ์ปฌ๋Ÿผ ํญ, ํ‹€๊ณ ์ •(ํ—ค๋”+๊ณ ์ • ์ปฌ๋Ÿผ). format์ด ์žˆ๋Š” ์ˆซ์žยท๋‚ ์งœ๋Š” ๋ฌธ์ž์—ด์ด ์•„๋‹ˆ๋ผ ์›์‹œ ๊ฐ’ + Excel ์„œ์‹์œผ๋กœ ๋‚˜๊ฐ€ ์—‘์…€์—์„œ ๋ฐ”๋กœ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค. { styled: false }๋Š” ์ด์ „(v2.28) ํ”Œ๋ ˆ์ธ ์ถœ๋ ฅ. ๊ทธ๋ฃน ํ–‰(groupBy ๋ผ๋ฒจยท์ง‘๊ณ„)์€ ์•„์ง ๋‚ด๋ณด๋‚ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ถ€์„œ๊ฐ€ mergeCells๋กœ ๋ณ‘ํ•ฉ๋˜๊ณ , ๊ธ‰์—ฌยท์ž…์‚ฌ์ผ์€ format ๊ทธ๋Œ€๋กœ ์—‘์…€ ์„œ์‹์ด ๋ฉ๋‹ˆ๋‹ค.

focusCell(rowIndex, field)๋Š” ํŽ˜์ด์ง€ ์ด๋™ยท์Šคํฌ๋กค์„ ํฌํ•จํ•ด ์…€์— ํฌ์ปค์Šค๋ฅผ ์ฃผ๊ณ , ensureRowVisible(row) / ensureColumnVisible(colId)๋Š” ํ–‰ยท์ปฌ๋Ÿผ์ด ๋ณด์ด๋„๋ก ์Šคํฌ๋กคํ•ฉ๋‹ˆ๋‹ค. getJson()์€ ํ•„ํ„ฐยท์ •๋ ฌ์ด ์ ์šฉ๋œ ํ˜„์žฌ ๋ทฐ๋ฅผ JSON ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์…€ ๋”๋ธ”ํด๋ฆญ์€ cellDoubleClicked ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

๋ ˆ์ด์•„์›ƒ ยท ์„ฑ๋Šฅ Layout & Performance

๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ์˜ ๊ฐ€์ƒํ™”์™€ ๊ทธ๋ฆฌ๋“œ๊ฐ€ ํ™”๋ฉด์„ ์ฐจ์ง€ํ•˜๋Š” ๋ฐฉ์‹.

Row Virtualization โ€” 100,000 rows

๋ณด์ด๋Š” ๋ฒ”์œ„(ยฑ6ํ–‰ ๋ฒ„ํผ)๋งŒ DOM์œผ๋กœ ๋ Œ๋”๋งํ•ด 10๋งŒ ํ–‰๋„ ์ง€์—ฐ ์—†์ด ์Šคํฌ๋กคํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ DOM row ์ˆ˜: โ€“

Column Virtualization โ€” 300 columns (virtualX)

virtualX: true๋Š” ๊ฐ€๋กœ ๋ทฐํฌํŠธ์— ๋ณด์ด๋Š” ์ปฌ๋Ÿผ(+๋ฒ„ํผ 2)๋งŒ ์…€์„ ๋ Œ๋”๋งํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ํญ ์ŠคํŽ˜์ด์„œ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค โ€” ์ˆ˜๋ฐฑ ๊ฐœ ์ปฌ๋Ÿผ์—์„œ๋„ ํ–‰ DOM์ด ๊ฐ€๋ณ๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๊ฐ€๋กœ ์Šคํฌ๋กค ์‹œ ์ปฌ๋Ÿผ ์ฐฝ์ด ๊ฐฑ์‹ ๋˜๊ณ , ๊ณ ์ •(pinned) ์ปฌ๋Ÿผ์€ ํ•ญ์ƒ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค.

๊ฐ€๋กœ๋กœ ์Šคํฌ๋กคํ•ด ๋ณด์„ธ์š”.

Pinned Top Rows ยท Wrap Text ยท Auto Height

pinnedTopRows๋Š” ํ—ค๋” ์•„๋ž˜์— ์Šคํฌ๋กค๊ณผ ๋ฌด๊ด€ํ•œ ๊ณ ์ • ํ–‰(ํ‘œ์‹œ ์ „์šฉ)์„ ๋‘๊ณ  setPinnedTopRows(rows)๋กœ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค. column.wrapText + autoRowHeight: true๋Š” ๊ธด ํ…์ŠคํŠธ๋ฅผ ์ค„๋ฐ”๊ฟˆํ•˜๊ณ  ํ–‰ ๋†’์ด๋ฅผ ๋‚ด์šฉ์— ๋งž์ถฐ ๊ณ„์‚ฐํ•˜๋ฉฐ(๊ฐ€๋ณ€ ๋†’์ด ๊ฐ€์ƒํ™”), domLayout: 'autoHeight'๋Š” ๊ทธ๋ฆฌ๋“œ๊ฐ€ ๋‚ด์šฉ ๋†’์ด๋งŒํผ ๋Š˜์–ด๋‚˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

Note ์ปฌ๋Ÿผ์€ wrapText โ€” ํ–‰ ๋†’์ด๊ฐ€ ๋‚ด์šฉ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋งจ ์œ„ ๊ตต์€ ํ–‰์ด pinnedTopRows์ž…๋‹ˆ๋‹ค.

Auto-Height Grid (domLayout)

domLayout: 'autoHeight'๋Š” ์ปจํ…Œ์ด๋„ˆ ๋†’์ด ๋Œ€์‹  ๋‚ด์šฉ ๋†’์ด๋งŒํผ ๊ทธ๋ฆฌ๋“œ๊ฐ€ ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค โ€” ์„ธ๋กœ ์Šคํฌ๋กค/๊ฐ€์ƒํ™”๊ฐ€ ์—†์–ด์ง€๋ฏ€๋กœ ์†Œ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ „์šฉ์ž…๋‹ˆ๋‹ค.

์ด ๊ทธ๋ฆฌ๋“œ๋Š” 8ํ–‰ ๋†’์ด๋งŒํผ๋งŒ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค (์ปจํ…Œ์ด๋„ˆ ๋†’์ด ๋ถˆํ•„์š”).

Fill Parent Height (domLayout: 'fill')

domLayout: 'fill'์€ ๊ทธ๋ฆฌ๋“œ๋ฅผ ๋ถ€๋ชจ ์ปจํ…Œ์ด๋„ˆ ๋†’์ด์— ์ •ํ™•ํžˆ ๋งž์ถฅ๋‹ˆ๋‹ค โ€” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์–ด๋„ ์ค„์ง€ ์•Š๊ณ , ๋งŽ์•„๋„ ๋ถ€๋ชจ๋ฅผ ๋„˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(๋„˜์น˜๋Š” ํ–‰์€ ๋ณธ๋ฌธ ์Šคํฌ๋กค). flex: 1๋กœ ์žก์€ ์˜์—ญ์ฒ˜๋Ÿผ ๋†’์ด๋ฅผ CSS๋กœ ๊ณ„์‚ฐํ•ด ์ฃผ๋Š” ๋ ˆ์ด์•„์›ƒ์— ์“ฐ์„ธ์š”. ๊ธฐ๋ณธ๊ฐ’ 'normal'์€ height: 100%๋ผ ๋ถ€๋ชจ๊ฐ€ flex ํ•ญ๋ชฉ์ด๋ฉด ์ž๋™ ์ตœ์†Œ ํฌ๊ธฐ(min-height: auto)์— ๋ฐ€๋ ค ํ–‰ ์ˆ˜๋งŒํผ ๋Š˜์–ด๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ฐ™์€ 400px ๋ถ€๋ชจ์— ๋‘ ๋ชจ๋“œ๋ฅผ ๋‚˜๋ž€ํžˆ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค โ€” ํ–‰ ์ˆ˜๋ฅผ ๋ฐ”๊ฟ” ๋ณด์„ธ์š”.

domLayout: 'fill'
๊ธฐ๋ณธ๊ฐ’ ('normal')
๋ฒ„ํŠผ์œผ๋กœ ํ–‰ ์ˆ˜๋ฅผ ๋ฐ”๊พธ๋ฉด ๋‘ ๊ทธ๋ฆฌ๋“œ์˜ ์‹ค์ œ ๋†’์ด๊ฐ€ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Headerless Grid (showHeader)

showHeader: false๋Š” ํ—ค๋” ์˜์—ญ ์ „์ฒด(์ •๋ ฌยทํ•„ํ„ฐ UI ํฌํ•จ)๋ฅผ ์ˆจ๊น๋‹ˆ๋‹ค โ€” ์ฝ๊ธฐ ์ „์šฉ ๋ฆฌ์ŠคํŠธ๋‚˜ ์ปค์Šคํ…€ ํ—ค๋”๋ฅผ ์ง์ ‘ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ—ค๋” ์—†์ด ๋ณธ๋ฌธ๋งŒ ๋ Œ๋”๋ง๋œ ๊ทธ๋ฆฌ๋“œ์ž…๋‹ˆ๋‹ค.

์ƒํƒœ ยท ๋Ÿฐํƒ€์ž„ ์ œ์–ด State & Runtime

๋งŒ๋“  ๋’ค์— ๋ฐ”๊พธ๋Š” ๊ฒƒ๋“ค โ€” ์ƒํƒœ ์ €์žฅยท๋ณต์›, ์˜ต์…˜ ๋ณ€๊ฒฝ, ์ด๋ฒคํŠธ, ์˜ค๋ฒ„๋ ˆ์ด.

Grid State Save & Restore

getState()๋Š” ์ปฌ๋Ÿผ ์ˆœ์„œยท์ˆจ๊น€ยทํญ, ์ •๋ ฌ, ํ•„ํ„ฐ, ํ€ต ํ•„ํ„ฐ, ๊ทธ๋ฃนํ•‘, ํŽ˜์ด์ง€ ์ƒํƒœ๋ฅผ JSON ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. localStorage ๋“ฑ์— ์ €์žฅํ–ˆ๋‹ค๊ฐ€ setState(state)๋กœ ๋ณต์›ํ•˜๊ณ , resetState()๋กœ ์ƒ์„ฑ ์‹œ์  ์˜ต์…˜ ๊ธฐ์ค€์œผ๋กœ ๋˜๋Œ๋ฆฝ๋‹ˆ๋‹ค (resetState({ sort: true })์ฒ˜๋Ÿผ ๋ถ€๋ถ„ ๋ฆฌ์…‹๋„ ๊ฐ€๋Šฅ).

์ •๋ ฌยทํ•„ํ„ฐยท์ปฌ๋Ÿผ ํญยท์ˆœ์„œ๋ฅผ ๋ฐ”๊พผ ๋’ค ์ €์žฅ โ†’ ๋‹ค์‹œ ํํŠธ๋Ÿฌ๋œจ๋ฆฌ๊ณ  ๋ณต์›ํ•ด ๋ณด์„ธ์š”.

Partial Refresh ยท Runtime Options ยท Title / Toolbar

refreshCell(row, field) / refreshRow(row) / refreshColumn(colId)์€ ์ „์ฒด ์žฌ๊ณ„์‚ฐ ์—†์ด ๋ Œ๋”๋œ DOM๋งŒ ๋‹ค์‹œ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค (๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ์—์„œ ์‹ค์‹œ๊ฐ„ ๊ฐ’ ๊ฐฑ์‹ ์šฉ). setOptions({...})๋Š” ์žฌ์ƒ์„ฑ ์—†์ด ์˜ต์…˜์„ ๋ฐ”๊พธ๋ฉฐ, title ์˜ต์…˜๊ณผ toolbar ์Šฌ๋กฏ (์†Œ๋น„์ž DOM ์ฃผ์ž…)์œผ๋กœ ๊ทธ๋ฆฌ๋“œ์— ์ƒ๋‹จ UI๋ฅผ ๋ถ™์ž…๋‹ˆ๋‹ค.

ํƒ€์ดํ‹€ ๋ฐ”์™€ ํˆด๋ฐ” ์Šฌ๋กฏ์€ ๊ทธ๋ฆฌ๋“œ ์•ˆ์— ๋ Œ๋”๋ง๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค (title / toolbar ์˜ต์…˜).

Utility Options & Events (v2.0)

once(event, fn)(1ํšŒ ํ•ธ๋“ค๋Ÿฌ) ยท setEnabled(bool)(์ „์ฒด ์ธํ„ฐ๋ž™์…˜ ์ž ๊ธˆ ์˜ค๋ฒ„๋ ˆ์ด) ยท column.headerAlign(ํ—ค๋”๋งŒ ๋‹ค๋ฅธ ์ •๋ ฌ) ยท showHeader: false(ํ—ค๋” ์ˆจ๊น€) ยท rowValueChanged(ํ–‰ ๋‹จ์œ„ ๋ณ€๊ฒฝ ๋ฌถ์Œ โ€” ํŽธ์ง‘ยท๋ถ™์—ฌ๋„ฃ๊ธฐยท์ฑ„์šฐ๊ธฐ ๊ณตํ†ต) ๋ชจ์Œ์ž…๋‹ˆ๋‹ค.

Salary ํ—ค๋”๋Š” headerAlign: 'center' โ€” ์…€์€ ์˜ค๋ฅธ์ชฝ ์ •๋ ฌ์ด์ง€๋งŒ ํ—ค๋”๋งŒ ๊ฐ€์šด๋ฐ์ž…๋‹ˆ๋‹ค.

Lifecycle & Cancelable Events

gridReady(์ดˆ๊ธฐ ๋ Œ๋” ํ›„ 1ํšŒ) ยท dataChanged(ํ–‰ ์ถ”๊ฐ€/์‚ญ์ œ/๊ต์ฒด) ยท viewRendered(๋ชจ๋“  refresh ํ›„) ๋ผ์ดํ”„์‚ฌ์ดํด ์ด๋ฒคํŠธ์™€, e.cancel = true๋กœ ๋™์ž‘์„ ๊ฑฐ๋ถ€ํ•˜๋Š” beforeSort / beforeSelectionChange / beforeCellSave ์ทจ์†Œ ๊ฐ€๋Šฅ ์ด๋ฒคํŠธ ๊ทœ์•ฝ์ž…๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ๋กœ๊ทธ๊ฐ€ ์—ฌ๊ธฐ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Overlays

๋กœ๋”ฉ ์Šคํ”ผ๋„ˆ ์˜ค๋ฒ„๋ ˆ์ด์™€ "No rows to show" ๋นˆ ์ƒํƒœ.

UI Text Localization (localeText)

๊ทธ๋ฆฌ๋“œ๊ฐ€ ์ง์ ‘ ๊ทธ๋ฆฌ๋Š” UI ๋ฌธ์ž์—ด(ํ•„ํ„ฐ ๋ฉ”๋‰ด ยท ํŽ˜์ด์ง€๋„ค์ด์…˜ ยท ์˜ค๋ฒ„๋ ˆ์ด ยท ๊ทธ๋ฃน ์š”์•ฝ ๋“ฑ)์€ localeText๋กœ ํ†ต์งธ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. ๋‚ด์žฅ ๋กœ์ผ€์ผ DataGrid.locales.ko / .en์„ ๊ทธ๋Œ€๋กœ ์“ฐ๊ฑฐ๋‚˜, ๊ทธ ์œ„์— ์›ํ•˜๋Š” ํ‚ค๋งŒ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. setOptions({ localeText })๋กœ ๋Ÿฐํƒ€์ž„ ์ „ํ™˜๋„ ๋ฉ๋‹ˆ๋‹ค. {from} ๊ฐ™์€ ํ† ํฐ์€ ๊ฐ’์œผ๋กœ ์น˜ํ™˜๋˜๋ฉฐ, ๋ฒˆ์—ญํ•˜์ง€ ์•Š์€ ํ‚ค๋Š” ์˜์–ด ๊ธฐ๋ณธ๊ฐ’์ด ๊ทธ๋Œ€๋กœ ์“ฐ์ž…๋‹ˆ๋‹ค.

ํ—ค๋”์˜ ํ•„ํ„ฐ ๋ฉ”๋‰ด(โ‰ก)๋ฅผ ์—ด์–ด ์—ฐ์‚ฐ์žยท๋ฒ„ํŠผ ๋ผ๋ฒจ์„, ์•„๋ž˜ ํŽ˜์ด์ง€๋„ค์ด์…˜ ๋ฐ”์™€ ๊ทธ๋ฃน ํ•ฉ๊ณ„ ํ–‰์„ ํ•จ๊ป˜ ํ™•์ธํ•˜์„ธ์š”.

License Key & Evaluation Watermark

ํ‚ค ์—†์ด ์‹คํ–‰ํ•˜๋ฉด ์ „ ๊ธฐ๋Šฅ์ด ๋™์ž‘ํ•˜๋Š” ํ‰๊ฐ€ํŒ โ€” ๊ฐœ๋ฐœ ํ˜ธ์ŠคํŠธ(localhost)๊ฐ€ ์•„๋‹Œ ๊ณณ์—์„œ๋Š” ์šฐํ•˜๋‹จ์— ์›Œํ„ฐ๋งˆํฌ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. DataGrid.setLicenseKey(key)๋กœ ๋“ฑ๋กํ•˜๊ณ  DataGrid.getLicenseInfo()๋กœ ํŒ์ • ์ƒํƒœ๋ฅผ ์ง„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐ๋ชจ๋Š” ๋‚ด๋ถ€ ํ›…์œผ๋กœ ํ˜ธ์ŠคํŠธ๋ฅผ ๋ฐ”๊ฟ”๊ฐ€๋ฉฐ ์›Œํ„ฐ๋งˆํฌยท์ƒํƒœ ์ „ํ™˜์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

๋ฒ„ํŠผ์œผ๋กœ ํ‚ค๋ฅผ ๋ฐ”๊ฟ” ๋ณด์„ธ์š” โ€” getLicenseInfo() ๊ฒฐ๊ณผ๊ฐ€ ์—ฌ๊ธฐ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋ Œ๋”๋Ÿฌ Renderers

์…€ ๊ฐ’์„ ํƒœ๊ทธยท์ฒดํฌยท์ง„ํ–‰๋ฐ” ๋“ฑ์œผ๋กœ ๊ทธ๋ฆฌ๋Š” ๋‚ด์žฅ ๋ Œ๋”๋Ÿฌ.

Built-in Renderers (tag / check / progress)

DataGrid.renderers.tag(colorMap)์€ ์ƒํƒœ ๊ฐ’์„ ์ƒ‰์ƒ ๋ฐฐ์ง€๋กœ, renderers.check()๋Š” ๋ถˆ๋ฆฌ์–ธ์„ โœ“/โ€“๋กœ, renderers.progress()๋Š” 0โ€“100 ๊ฐ’์„ ์ง„ํ–‰ ๋ฐ”๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋ Œ๋”๋Ÿฌ๋Š” ํ‘œ์‹œ๋งŒ ๋ฐ”๊พธ๋ฉฐ ์ •๋ ฌยทํ•„ํ„ฐยท๋‚ด๋ณด๋‚ด๊ธฐ๋Š” ์›์‹œ ๊ฐ’ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค.

Status๋กœ ์ •๋ ฌํ•ด ๋ณด๋ฉด ํ‘œ์‹œ๋Š” ๋ฐฐ์ง€์ง€๋งŒ ์ •๋ ฌ์€ ์›์‹œ ๋ฌธ์ž์—ด ๊ธฐ์ค€์ž„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Select Renderer (DataGrid.renderers.select)

select ์—๋””ํ„ฐ์˜ ์ง๊ฟ ๋ Œ๋”๋Ÿฌ์ž…๋‹ˆ๋‹ค โ€” ์…€์—๋Š” ์ฝ”๋“œ(value)๊ฐ€ ์ €์žฅ๋ผ ์žˆ์–ด๋„ cellRenderer: DataGrid.renderers.select()๊ฐ€ ๊ทธ ์ปฌ๋Ÿผ์˜ editorOptions์—์„œ label์„ ์ฐพ์•„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐยท์ •๋ ฌยทํ•„ํ„ฐยท๋‚ด๋ณด๋‚ด๊ธฐ๋Š” ์ €์žฅ๋œ value ๊ธฐ์ค€ ๊ทธ๋Œ€๋กœ์ด๊ณ , ํ‘œ์‹œ๋งŒ label๋กœ ๋ฐ”๋€๋‹ˆ๋‹ค. ๋ชฉ๋ก์— ์—†๋Š” ๊ฐ’์€ ์›๋ž˜ ํ‘œ์‹œ๋กœ ํด๋ฐฑํ•˜๋ฉฐ, ๋‹ค๋ฅธ ๋ชฉ๋ก์„ ์“ฐ๋ ค๋ฉด DataGrid.renderers.select([{ label, value }, โ€ฆ])์ฒ˜๋Ÿผ ์ง์ ‘ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Country ์…€์€ ๋ฐ์ดํ„ฐ์— 'kr' ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์ €์žฅ๋ผ ์žˆ์ง€๋งŒ ํ™”๋ฉด์—๋Š” label์ด ๋ณด์ž…๋‹ˆ๋‹ค โ€” ํŽธ์ง‘ํ•ด ๋ณด์„ธ์š”.

๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.