WebGrid 사용법
빌드 없는 순수 HTML5 그리드. 아래 예제는 전부 이 페이지에서 실시간 동작합니다.
1. 시작하기
<div id="grid" style="height:300px;overflow:auto"></div>
<script src="./webgrid.js"></script>
<link rel="stylesheet" href="./webgrid.css" />
<script>
const grid = new WebGrid({
el: document.getElementById("grid"),
columns: [
{ name: "id", title: "번호", width: 72 },
{ name: "title", title: "제목", width: 300 },
],
data: [{ id: 1, title: "첫글" }],
rowHeaders: ["rowNum"],
});
</script>
2. 데이터
배열 / URL / readData (포락·문자열도 직접 수용)
new WebGrid({ el, columns, data: rows }); // 배열 직접
new WebGrid({ el, columns, dataUrl: "./data.json" }); // 자동 로드
grid.resetData(json); // ajax 응답 그대로: {data:[...]}/{rows:[...]}/JSON문자열 모두 됨
grid.setData(json); // resetData와 동일
grid.readData(); // dataUrl 재조회
grid.readData("./board-large.json"); // URL 지정
grid.readData(1, { title: "점검" }, true); // 페이지+파라미터 (서버 검색)
grid.reload(); // 저장된 파라미터로 재조회
grid.setRequestParams({ title: "점검" });
grid.loadData(rows); grid.setData(rows); grid.resetData(rows);
서버 응답 형태: [row], {data:[...]},
{contents:[...]}, {data:{contents, pagination}},
{rows:[...]}. 다른 모양이면 setParseResponse((payload, request) => rows | {rows, pagination}) 으로 변환.
3. 컬럼·에디터
{ name: "title", title: "제목", width: 300, align: "left",
editOptions: { type: "text" }, // text/select/checkbox/password/date/number/popup
sortable: true, validation: { required: true } }
4. 행헤더·체크박스·선택행 읽기
rowHeaders: ["rowNum", "checkbox"] // 번호+체크박스 (단일: "indicator"/"sequence"/"checkbox"/false) grid.checkRow(1); grid.uncheckRow(1); grid.checkAll(); grid.uncheckAll(); const aaa = grid.getSelected(); // 체크된 행 모음 aaa(0)["title"]; aaa[0]["제목"]; aaa.length; aaa.toArray(); [...aaa]
5. 선택·복사·붙여넣기
드래그 선택, Ctrl+C 복사(TSV), 붙여넣기는 편집 가능 셀에만 기록,
Ctrl+Z/Y 실행취소/다시실행, Shift+방향키 확장,
Shift+PageDown 페이지 확장, Ctrl+Shift+↓ 끝까지 확장,
Ctrl+A 전체 선택. 화면 밖 행도 선택·복사됩니다.
grid.select(2, "title"); grid.selectAll(); grid.serializeSelection(); grid.copySelection(); grid.pasteText(text);
6. 정렬·필터·페이징·요약
grid.sort("views", "desc"); grid.unSort(); // 헤더 클릭도 동일
grid.filter("status", "공개"); grid.unfilter(); grid.clearFilter();
grid.setPage(2); grid.setPerPage(20); grid.getPagination();
grid.setSummary({ columnContent: { views: { type: "sum" } } });
7. 유효성검사
grid.validate(); // → [{ rowIndex, errors: [{ columnName, value, errorCode }], row }]
8. 가상스크롤·행 높이·스크롤 영역
30행 이상이면 가상 렌더가 자동 적용됩니다 (화면 구간+여유분만 DOM 생성).
해제하려면 virtualScrolling: false.
new WebGrid({ el, columns, data,
virtualScrolling: { rowHeight: 28, overscan: 10, threshold: 30 },
rowHeight: 25, // 행 높이(px)
bodyHeight: 550, // 그리드 자체 스크롤 높이
});
9. 찾기·날짜 에디터
{ name: "writer", title: "작성자",
editOptions: { type: "popup", searchTitle: "작성자 찾기",
onSearch: ({ commit }) => openMyLookup((v) => commit(v)) } }
{ name: "createdAt", title: "등록일", editOptions: { type: "date", min: "2026-01-01" } }
셀에 🔍/📅 표시가 붙고, 돋보기를 누르면 onSearch가 호출됩니다.
없으면 grid.on("search", ...) 이벤트, 그것도 없으면 기본 입력창으로 확정.
조회 팝업은 class="webgrid-popup" 을 달아야 셀 편집이 유지됩니다.
팝업 안에 조회용 WebGrid를 넣고 체크된 값을
commit(sel(0)["name"]) 으로 반환할 수 있습니다.
10. 복합헤더
{ title: "생성", children: [
{ name: "creator", title: "작성자", width: 100 },
{ name: "createdAt", title: "작성일시", width: 130 } ] }
11. 테마
grid.setTheme("clean"); // clean/striped
grid.setTheme({ "--accent": "#7c3aed" }); // 변수 직접
WebGrid.applyTheme("clean"); // 전체 인스턴스
12. TOAST UI Grid 교체
기존 new tui.Grid({...}) 코드는 그대로 두고 스크립트만 교체:
<script src="./webgrid.js"></script> <script src="./tui-compat.js"></script> <link rel="stylesheet" href="./webgrid.css" />
자동 처리: header, sortable:"true",
hidden, minWidth, color,
renderer/editor 클래스(TOAST 규약),
rowHeight, bodyHeight,
columnOptions.frozenCount,
applyTheme, getRow().rowKey.
미지원(무시): header.height, selectionUnit:'row',
복합헤더+고정 병행.
확장 기능 (0.10.0)
0.10.1: 셀 드래그 중 상하·좌우 가장자리에서 자동 스크롤하며, 대각선 드래그도 지원합니다. 포인터가 움직이지 않아도 새로 드러난 셀까지 선택을 확장합니다. 중앙 복귀·마우스 해제·스크롤 끝에서 멈추며, 고정 열 위의 세로 선택은 해당 열을 유지합니다.
엑셀식 필터 메뉴
0.12.0부터 필터 메뉴는 기본 숨김이며, 컬럼에 filterable: true를 명시한 경우에만 헤더의 ▾가 나타납니다. filterMenu: false는 모든 컬럼의 메뉴를 숨깁니다. 프로그램에서 호출하는 filter/unfilter API는 이 설정과 독립적으로 사용할 수 있습니다.
각 헤더의 ▾에서 값 검색·체크 선택과 문자 포함/같음, 숫자·날짜 범위, 빈 값 조건을 조합합니다. 조건과 체크 값은 AND로 적용됩니다. 목록 검색은 체크 값을 바꾸지 않으며 “검색된 값 전체 선택”은 검색에 일치하는 값만 선택·해제합니다. 300개보다 많은 값은 검색으로 좁힐 수 있습니다. 적용하기 전의 변경은 취소/Escape로 버릴 수 있습니다.
new WebGrid({ el, data, columns: [
{ name: 'dept', header: '부서', filterable: true }, // 이 열에만 필터 메뉴 표시
{ name: 'id', header: '번호' } // 기본: 필터 메뉴 숨김
] });
// filterMenu: false를 지정하면 filterable:true인 열도 메뉴 숨김.
// openFilterMenu는 활성화된 열만 허용하며 filter/unfilter API는 메뉴 설정과 독립.
grid.filter('dept', { values: ['영업팀', '개발팀'] });
grid.filter('amount', { dataType: 'number', operator: 'between', value: 100, valueTo: 1000 });
grid.filter('date', { dataType: 'date', operator: 'gte', value: '2026-10-01' });
grid.filter('title', { operator: 'contains', value: '점검' });
grid.unfilter('dept'); grid.unfilter();
grid.openFilterMenu('dept'); // filterable:true로 선언한 열
고정 열과 이동 열의 같은 데이터 행은 hover 배경색을 함께 표시합니다. TOAST 테마의 row.hover.background 색을 사용하며 선택·활성·편집 셀의 표시는 유지합니다. 부모와 독립 하위 그리드의 hover는 각각 처리합니다. 이동 영역에 가로 스크롤바가 있을 때 고정 영역에도 같은 높이의 비활성 네이티브 스크롤바를 표시하므로 데이터 영역과 마지막 행 높이가 일치합니다.
다중 정렬 · 선택 영역 통계
일반 헤더 클릭은 단일 정렬, Shift+클릭은 기존 기준에 추가합니다. 오름차순 → 내림차순 → 해제 순서이며 헤더의 숫자가 정렬 우선순위입니다. 원본 행 배열은 유지하고 표시 순서만 바꿉니다. 복사·붙여넣기·키보드 이동·선택 통계는 현재 화면의 행 순서에 따릅니다.
grid.setSortModel([
{ columnName: 'dept', direction: 'asc' },
{ columnName: 'amount', direction: 'desc' }
]);
grid.getSortModel();
grid.unSort(); // 편집 값과 체크 상태 유지
grid.getSelectionStatistics();
// { cellCount, count, numericCount, sum, avg, min, max }
// 통계 표시는 기본 false. 표시하려면 생성 옵션을 켭니다.
new WebGrid({ el, columns, data, selectionStatistics: true });
숫자의 천 단위 쉼표를 인식합니다. 예를 들어 셀의 "1,234.50"은 1234.5로 집계됩니다. 숫자 정렬·필터·수식·그룹 집계에도 같은 숫자 판정이 적용됩니다. "1,2"처럼 잘못된 구분 형식이나 일반 문자는 숫자로 집계하지 않습니다.
셀 수식: 열 번호 규칙
편집 가능한 셀에 수식을 입력하거나 setValue()로 지정합니다. 열 번호는 1부터 시작하며 행 번호/체크 헤더는 제외하고, 컬럼 정의의 리프 열 순서를 사용합니다. 숨긴 열도 번호에 포함됩니다. 정렬·필터·페이지·그룹 접기는 수식 참조를 바꾸지 않습니다.
| 입력 | 계산 범위 |
|---|---|
=sum(1:5) | 현재 행의 1~5열 |
=sum(1,3,5) | 현재 행의 1·3·5열 |
=sum(1) | 현재 로드된 모든 원본 행의 1열 (필터·페이지와 무관) |
=sum(1:1) | 현재 행의 1열만 참조 |
=sum(1:3,5) | 현재 행의 1~3열과 5열 |
지원 함수: SUM, AVG(AVERAGE도 가능), COUNT, COUNTA, MIN, MAX, PRODUCT, MEDIAN, VAR, STDEV. 대소문자와 인수 앞뒤 공백을 허용합니다. COUNT는 숫자/숫자 문자열의 개수, COUNTA는 비어 있지 않은 값의 개수입니다. 나머지 수치 함수는 빈 값·문자·불리언을 제외합니다. VAR/STDEV는 표본 분산/표본 표준편차입니다.
grid.setValue(0, 'total', '=sum(1:5)'); grid.getValue(0, 'total'); // 원본 수식 문자열 grid.getCalculatedValue(0, 'total'); // 계산 값 grid.recalculate(); // 재계산 + 화면 갱신 // 생성 옵션 formulas: false 로 수식 해석 비활성화
참조 대상에 자신이 포함되면 #CYCLE!을 표시합니다. 예를 들어 1열 자체에 =sum(1)을 입력하면 순환 참조입니다. 잘못된 열은 #REF!, 잘못된 문법은 #ERROR!, 미지원 함수는 #NAME?, 숫자가 없는 평균이나 표본이 부족한 VAR/STDEV는 #DIV/0!입니다. A1 주소, 산술 연산식, 중첩 함수와 숫자 상수 인수는 이번 문법에 포함하지 않습니다.
행 그룹 · 그룹별 소계 · 전체 합계
new WebGrid({ el, columns, data,
grouping: {
columns: ['dept', 'status'], // 배열 순서대로 다단 그룹
aggregates: { amount: 'sum', quantity: 'sum', score: 'avg' },
subtotals: true, // 기본 true
grandTotal: true, // 기본 true
labelColumn: 'dept' // 생략 시 첫 번째 표시 열
}
});
grid.setGrouping({ columns: [], aggregates: { amount: 'sum' } }); // 전체 합계만
grid.setGrouping(null); // 그룹/합계 해제
grid.toggleGroup(groupKey, false); // 접기; true는 펼치기
grid.expandAllGroups(); grid.collapseAllGroups();
grid.getGroupSummary(groupKey); // { key, count, values }
grid.getGrandTotal(); // { amount: ..., quantity: ... }
그룹 키는 그룹 행의 data-group-key 또는 groupToggle 이벤트에서 얻습니다. 그룹 소계는 현재 페이지 내 해당 그룹의 데이터, 전체 합계는 페이지와 접기 상태에 관계없이 필터를 통과한 모든 로드 데이터를 계산합니다. 서버에 아직 로드하지 않은 행은 포함하지 않습니다. 집계에는 위 수식 함수명 또는 (values, rows) => value 콜백을 사용할 수 있습니다. 계산 열도 집계할 수 있습니다.
실제 XLSX 내보내기
grid.exportXlsx('실적.xlsx', { sheetName: '실적' });
const bytes = grid.toXlsx(); // Uint8Array: 저장/전송에 사용 가능
grid.exportXlsx('현재페이지.xlsx', { currentPage: true });
grid.exportXlsx('전체원본.xlsx', { allData: true, includeHidden: true });
외부 라이브러리나 CDN 없이 Open XML ZIP 파일을 생성합니다. 기본값은 보이는 열과 필터·정렬을 적용한 전체 로드 행이며, 접힌 그룹도 펼친 형태로 소계·전체 합계와 함께 내보냅니다. XLSX의 헤더, 열 너비, 숫자/통화/퍼센트 형식을 제공합니다. 날짜 문자열은 문자열로 유지합니다. 사용자 정의 열 번호 수식은 계산된 값으로 저장하며, 하위 그리드는 자신의 exportXlsx()로 따로 내보낼 수 있습니다. allData는 필터·정렬·그룹을 제외한 원본 행만 내보냅니다.
트리 형태의 하위 그리드 · 펼칠 때 조회
new WebGrid({ el, columns, data,
detail: {
hasChildren: row => row.hasChildren, // 생략하면 모든 행에 + 표시
bodyHeight: 220,
load: async ({ row, rowIndex, grid, signal }) => {
const response = await fetch('/api/detail?id=' + encodeURIComponent(row.id), { signal });
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.json(); // { columns: [...], data: [...] }
},
columns: [{ name: 'item', header: '품목' }], // 응답 columns 없을 때 사용
gridOptions: { rowHeaders: ['rowNum'] }
}
});
const child = await grid.expandRow(rowKey);
grid.collapseRow(rowKey); await grid.toggleRow(rowKey);
grid.getDetailGrid(rowKey); // WebGrid 또는 null
await grid.reloadDetail(rowKey); // 캐시 제거 후 재조회
첫 펼침에 조회하며 중복 요청을 방지합니다. 접었다가 펼치면 조회 결과와 하위 편집 상태를 유지합니다. 조회 실패 시 “다시 시도” 버튼을 제공합니다. load 대신 url(문자열 또는 컨텍스트를 받는 함수), fetchOptions, parseResponse를 사용할 수 있습니다. 응답은 배열 또는 {columns, data} / {columns, rows}이며, 응답의 gridOptions와 detail로 손자 그리드도 구성할 수 있습니다. 서버 응답에 columns가 없으면 detail.columns, 마지막으로 상위 columns를 사용합니다.
하위 행은 헤더가 다른 독립적인 WebGrid이며, 상위 선택/수식/소계에는 포함하지 않습니다. 0.11.0부터 펼친 상태에도 상위 가상 렌더를 유지하며, 실측한 상세 높이를 누적해 화면 범위를 계산합니다. 고정 열은 펼친 동안 sticky 방식으로 전환하고 모두 접으면 분할 고정 열로 돌아갑니다. 화면 밖의 하위 인스턴스는 편집 원문·내부 스크롤 보존을 위해 캐시에 남으며, 데이터 교체·행 삭제·destroy 시 인스턴스/observer/요청을 정리합니다. 화면 밖 행에 expandRow()를 호출하면 조회를 마쳐도 아직 하위 DOM을 생성하지 않아 null을 반환할 수 있습니다. 실제 하위 인스턴스는 화면에 들어올 때 생성하며 detailReady에서 받을 수 있습니다.
추가 이벤트: sort / selectionStatistics / groupToggle / detailLoadStart / detailLoadSuccess / detailLoadError / detailReady / detailCollapse. detailReady에서 실제 생성된 하위 grid를 받습니다.
BOM 트리와 가변 높이 가상 스크롤 (0.11.0)
BOM · 상세 가상 스크롤 통합 데모 · 트리 회귀 검증
같은 헤더의 BOM 모드
tree는 하나의 그리드에서 같은 열을 사용하는 계층입니다. 지정한 열에 들여쓰기와 펼침 버튼을 표시하며 부모·자식·손자 모두 같은 선택/편집/클립보드/수식 API를 사용합니다. 기본은 접힌 상태입니다.
const grid = new WebGrid({
el, bodyHeight: 400,
columns: [
{ name: 'partNo', header: 'Part No', width: 300 },
{ name: 'qty', header: 'Qty', width: 100, edit: true }
],
tree: { columnName: 'partNo', idField: 'lineId',
childrenField: 'children', indent: 18, initiallyExpanded: true },
data: [{ lineId: 'P1', partNo: 'Parent1', qty: 1, children: [
{ lineId: 'C1', partNo: 'Child1', qty: 2, children: [
{ lineId: 'CC1', partNo: 'CChild1', qty: 3 }
] },
{ lineId: 'C2', partNo: 'Child2', qty: 4 }
] }]
});
idField의 기본값은 id입니다. Part No는 여러 조립품에서 반복될 수 있으므로 ID는 부품 번호와 구분된 고유한 BOM 행 ID를 사용하는 것이 좋습니다. ID가 제공되면 중복을 검사합니다. children은 배열이어야 하며 순환 관계를 거부합니다. 입력 원본 배열을 변경하지 않습니다.
id / parentId 형태의 평탄한 입력
tree: { columnName: 'partNo', idField: 'id', parentIdField: 'parentId' },
data: [
{ id: 'C1', parentId: 'P1', partNo: 'Child1', qty: 2 },
{ id: 'P1', parentId: null, partNo: 'Parent1', qty: 1 },
{ id: 'CC1', parentId: 'C1', partNo: 'CChild1', qty: 3 }
]
입력 순서와 관계없이 계층을 구성합니다. parentId가 null/빈 문자열인 행은 루트입니다. ID의 타입도 일치해야 하며, 없는 부모·중복 ID·순환 부모 관계는 오류로 처리합니다. 구조를 바꾸거나 ID/parentId를 재지정하려면 loadData/resetData로 일관된 전체 구조를 다시 적용하세요.
BOM도 펼칠 때 조회
tree: {
columnName: 'partNo',
hasChildren: 'hasChildren', // 기본 필드. (row, rowKey, grid) => boolean도 가능
load: async ({ row, rowIndex, grid, signal }) => {
const response = await fetch('/api/bom?parentId=' + encodeURIComponent(row.id), { signal });
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.json(); // 직접 자식 배열 또는 { data: [...] } / { rows: [...] }
}
},
data: [{ id: 'P1', partNo: 'Parent1', hasChildren: true }]
응답은 같은 상위 열의 필드로 구성합니다. 직접 자식마다 hasChildren을 주면 손자를 나중에 조회할 수 있으며, 자식에 children 배열을 넣어 여러 단계를 한 번에 로드할 수도 있습니다. 기존 상세 모드와 마찬가지로 url/fetchOptions/parseResponse도 지원합니다. BOM에는 새 columns 헤더를 생성하지 않습니다.
한 행의 동시 펼침은 하나의 요청으로 합치고 접었다가 펼치면 캐시를 사용합니다. 접힌 뒤 도착한 응답은 저장만 하며 자동으로 펼치지 않습니다. 조회 오류의 ! 버튼은 재시도하며 빈 자식 응답은 리프로 바뀝니다. 데이터 교체·행 삭제·destroy 후 늦은 응답은 적용하지 않습니다. 서버에서 조회한 자식은 기존 데이터로 등록하므로 getModifiedRows()의 createdRows로 분류하지 않습니다.
트리 API와 데이터 저장
await grid.expandRow(rowKey); // tree 모드에서는 자식 rowKey 배열 반환
grid.collapseRow(rowKey);
await grid.toggleRow(rowKey);
// 명시적인 이름도 지원: expandTreeRow / collapseTreeRow
grid.expandAllTree(); // 이미 로드된 노드만 펼침. 추가 서버 조회 없음
grid.collapseAllTree();
grid.getTreeInfo(rowKey);
// { rowKey, parentRowKey, depth: 0부터, level: 1부터,
// children: [rowKey], expanded, loaded, loading, hasChildren }
grid.appendTreeRow(parentRowKey, { id: 'NEW', partNo: '새 부품' });
grid.appendRow({ id: 'ROOT', partNo: '새 루트' });
grid.removeRow(rowKey); // 로드된 하위 노드도 함께 삭제
grid.getData(); // 로드된 전체 노드의 평탄한 복사본
grid.getTreeData(); // children 배열을 재구성한 계층 복사본
grid.exportJson('BOM.json'); // BOM 모드에서는 계층 구조로 저장
grid.exportXlsx('BOM.xlsx'); // 로드된 노드의 들여쓰기와 outline level 포함
rowKey는 내부 원본 인덱스이며 서버 ID와 다릅니다. 펼침 조회는 자식을 원본 배열 뒤에 적재하고 표시 위치만 부모 아래로 연결하므로 기존 rowKey와 수정/체크 상태는 유지합니다. 삭제 시에는 인덱스를 재배치합니다. 헤더 정렬은 형제끼리 적용하며, 필터는 로드된 노드만 검색하고 일치 노드의 조상을 함께 표시합니다. 필터를 해제하면 기존 펼침 상태로 돌아갑니다. 페이지 크기는 루트 개수 기준이므로 자식이 다른 페이지로 분리되지 않습니다.
BOM 수식은 로드된 전체 원본 노드를 참조합니다. 생성 옵션 grouping: { columns: [], aggregates: {...} }로 전체 합계를 추가할 수 있으며 부모와 자식의 수치는 각각 한 행으로 집계합니다. 별도의 행 그룹(columns가 있는 grouping) 및 detail 모드와 tree 모드는 동시에 사용할 수 없습니다. 해당 구성이 필요하면 독립 상세 그리드의 gridOptions.tree로 하위 BOM을 구성할 수 있습니다.
펼친 상세 영역을 포함한 가상 스크롤
독립 상세 그리드는 bodyHeight가 정해진 영역을 사용하고, 상위는 각 상세 영역의 실측 높이와 일반 행 높이를 누적합니다. 로딩/조회 완료/오류/통계 표시/너비 변경으로 높이가 달라져도 화면 맨 위에 보이던 항목을 기준으로 스크롤 위치를 보정합니다. 화면 밖 하위 DOM은 문서에서 분리하며 데이터와 작성 중인 입력·내부 스크롤은 유지합니다. 하위 API 수정은 다시 표시될 때 반영합니다.
상위와 하위 모두 가상화되며, 키보드 포커스 및 scrollToRow는 상세 높이까지 반영합니다. 고정 열은 독립 상세가 펼쳐진 동안 sticky 방식, BOM에서는 기존 분할 팬 방식을 사용합니다. 가상화는 DOM 수를 줄이며 이미 로드한 데이터/하위 인스턴스 캐시 자체를 제거하지는 않습니다. 오래 유지할 필요가 없는 캐시는 데이터 초기화 또는 destroy로 정리할 수 있습니다.
추가 트리 이벤트: treeLoadStart / treeLoadSuccess / treeLoadError / treeExpand / treeCollapse. treeLoadSuccess에서 rowIndex와 로드된 rowKeys를 받습니다.
이전 버전으로 복원
수정 전 0.10.2의 원본 22개 파일과 SHA-256 목록은 savepoints/2026-10-15-before-tree-virtualization에 보관했습니다. PowerShell 7에서 아래 명령으로 원복할 수 있습니다. 먼저 현재 파일을 별도 ZIP으로 백업한 다음 원본 파일을 복원하며, 추가 데모/검증 파일과 Git 이력은 지우지 않습니다.
pwsh -File .\savepoints\2026-10-15-before-tree-virtualization\restore.ps1 # 별도 폴더에 복원하려면 -TargetPath '복원할 경로' 지정
13. API 레퍼런스
| 분류 | 메서드 |
|---|---|
| 데이터 | readData / reload / loadData / setData / resetData / clear / getData / getRow / getRowCount / setRow / appendRow / removeRow / getValue / setValue / getModifiedRows / clearModifiedData |
| 컬럼·스타일 | getColumns / setColumns / setColumnWidth / setColumnEditable / setColumnVisible / setColumnStyle / setCellStyle / clearCellStyle / setTheme |
| 포커스·위치 조회 | getFocusedCell / focus / focusAt / getElement / getRowAt / getIndexOfRow / getIndexOfColumn / getCheckedRowKeysgetFocusedCell(): { rowKey, columnName, value }. 빈 데이터 또는 유효한 셀이 없으면 각 값은 null. 초기 활성 셀은 첫 셀. focus(rowKey, columnName, setScroll = true), focusAt(rowIndex, columnIndex, setScroll = true): 성공 여부(boolean) 반환. focusAt/getRowAt/getIndexOfRow는 현재 화면의 정렬·필터·페이지 순서, 컬럼 인덱스는 보이는 컬럼 기준. rowKey는 원본 데이터 인덱스. getElement(): 렌더링된 셀 DOM 또는 null(가상 스크롤 밖의 셀 포함). |
| 행헤더·체크 | getRowHeader / setRowHeader / checkRow / uncheckRow / checkAll / uncheckAll / getCheckedRowIndexes / getCheckedRowKeys / getCheckedRows / getSelected |
| 선택·클립보드 | select / selectAll / getSelectedRow / getSelection / serializeSelection / copySelection / pasteText / clearSelection / undo / redogetSelectedRow(): 현재 활성 셀의 행 데이터(rowKey 포함). 빈 그리드는 null, 초기 활성 행은 첫 행. |
| 정렬·필터·페이징·요약 | sort / unSort / filter / unfilter / clearFilter / getFilteredData / setPage / getPage / setPerPage / getPagination / setSummary / getSummary / setSummaryColumnContent |
| 가상스크롤 | setVirtualScrolling / isVirtualEnabled / scrollToRow |
| 확장 기능 | openFilterMenu / setSortModel / getSortModel / getSelectionStatistics / getCalculatedValue / recalculate / setGrouping / toggleGroup / expandAllGroups / collapseAllGroups / getGroupSummary / getGrandTotal / toXlsx / exportXlsx / expandRow / collapseRow / toggleRow / reloadDetail / getDetailGrid |
| BOM 계층 | expandTreeRow / collapseTreeRow / expandAllTree / collapseAllTree / getTreeInfo / getTreeData / appendTreeRow |
| 기타 | render / refresh / destroy / exportCsv / exportJson / toCsv / validate / finishEdit |
14. 이벤트
const off = grid.on("loadSuccess", ({ rows, loadedAt }) => {});
grid.off("loadSuccess", handler);
// loadStart/loadSuccess/loadError/load/change/check/checkAll/filter/page/search/select
// 그리드 엘리먼트에서도 webgrid:이벤트명 으로 수신 (예: webgrid:loadSuccess)