코드로 행 찾고 바꾸기
getRowById, getRowIndex, getDisplayedRows, forEachRow, getCellValue, setCellValue, refreshCells, getFocusedCell, setFocusedCell로 데이터를 다시 넣지 않고 행과 셀을 읽고 바꿉니다.
실행 예제행 API
id로 행 찾기, 셀 하나 바꾸기, 다시 그리기, 포커스 옮기기.
이 데모의 코드
import { createGrid } 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 grid = createGrid(ctx.host, {
columns: [
{ field: 'id', header: 'ID', type: 'number', width: 80 },
{ field: 'name', header: h('Name', '이름'), width: 170, editable: true },
{ field: 'status', header: h('Status', '상태'), width: 120, editable: true },
{ field: 'q1', header: h('Q1', '1분기'), type: 'number', format: '#,##0', width: 120, editable: true },
],
data: makeRows(2000), locale: ctx.lang, getRowId: r => String(r.id), filterRow: true,
});
const id = document.createElement('input');
id.type = 'number';
id.value = '1500';
id.style.width = '6em';
id.setAttribute('aria-label', h('Row id', '행 id'));
ctx.controls.append(id);
button(ctx, h('Find and focus', '찾아서 포커스'), () => {
const row = grid.getRowById(id.value);
const at = grid.getRowIndex(id.value);
if (!row) return ctx.log(h(`no row ${id.value}`, `${id.value}번 행 없음`));
if (at < 0) return ctx.log(h(`#${id.value} is filtered out`, `#${id.value}는 필터에 걸려 안 보임`));
grid.setFocusedCell(at, 'name');
ctx.log(`getRowIndex('${id.value}') = ${at} · ${row.name}`);
});
button(ctx, h('Set Q1 to 99,999 (undoable)', '1분기를 99,999로(실행 취소 가능)'), () => ctx.log(`setCellValue → ${grid.setCellValue(id.value, 'q1', 99999)}`));
button(ctx, h('Change outside + refreshCells', '밖에서 바꾸고 refreshCells'), () => {
const row = grid.getRowById(id.value);
if (!row) return;
row.status = row.status === 'Active' ? 'Pending' : 'Active';
grid.refreshCells({ rows: [row], flash: true });
});
separator(ctx);
button(ctx, h('Focused cell', '포커스 셀'), () => {
const f = grid.getFocusedCell();
ctx.log(f ? `row ${f.rowIndex}, ${f.colId}: ${String(grid.getCellValue(f.row ?? '', f.colId))}` : 'null');
});
button(ctx, h('Sum of shown Q1', '보이는 1분기 합계'), () => {
let sum = 0;
grid.forEachRow(r => (sum += r.q1), 'displayed');
ctx.log(`${grid.getDisplayedRows().length} rows, Q1 = ${sum.toLocaleString()}`);
});
text(ctx, h('After "Find and focus" the arrow keys and Enter work from that cell. Ctrl+Z undoes setCellValue; refreshCells only repaints.',
'"찾아서 포커스" 뒤에는 화살표와 Enter가 그 셀에서 이어집니다. setCellValue는 Ctrl+Z로 되돌리고, refreshCells는 다시 그리기만 합니다.'));
return grid;
}대부분의 변경은 데이터로 합니다. 새 목록은 setData, 바뀐 행은 applyTransaction. 그 사이의 작은 일(사용자가 있는 행 읽기, 셀 하나 바꾸기, 행이 어디 보이는지 찾기)에 아래 메서드를 쓰세요. 행은 getRowId의 id로 찾으니 지정해 두세요.
행 찾기
| 이름 | 타입 | 설명 |
|---|---|---|
getRowById(id) | Row | undefined | 이 id의 행(보이든 걸러졌든). 서버 데이터는 불러온 행만. |
getRowIndex(rowOrId) | number | 정렬·필터·그룹 뒤 행이 보이는 위치. 안 보이면 -1. scrollToRow, setFocusedCell과 함께 쓰세요. |
getDisplayedRowAt(index) | Row | undefined | 표시 위치의 데이터 행. 그룹·상세·아직 안 불러온 행은 undefined. |
getDisplayedRows() | Row[] | 보이는 순서의 데이터 행(그룹 행 제외). |
forEachRow(fn, scope?) | void | 데이터의 모든 행('all', 기본, 데이터 순서) 또는 보이는 데이터 행('displayed')마다 fn(row, index). |
const grid = createGrid(el, { columns, data, getRowId: r => String(r.id) });
const order = grid.getRowById('42');
const where = grid.getRowIndex('42'); // -1 when filtered out
if (where >= 0) grid.scrollToRow(where);
const shown = grid.getDisplayedRows(); // what the user sees, in order
let total = 0;
grid.forEachRow(r => (total += r.amount), 'displayed');셀 읽고 바꾸기
| 이름 | 타입 | 설명 |
|---|---|---|
getCellValue(rowOrId, colId) | unknown | 그리드가 읽는 값: valueGetter, 중첩 필드, 수식 결과. |
setCellValue(rowOrId, colId, value) | boolean | 편집처럼 셀 하나에 씀: 실행 취소, 변경 표시, 의존 컬럼 비우기, cellValueChanged. 규칙은 검사하지 않음. 행·컬럼이 없거나 값이 같으면 false. |
refreshCells({ rows?, colIds?, flash? }) | void | 행 객체를 직접 바꾼 뒤 다시 그림: 준 행(또는 id) 또는 전체. flash면 실시간 업데이트처럼 깜빡임. 정렬·필터는 다시 돌지 않음. |
// one cell, undoable, marked as changed
grid.setCellValue('42', 'status', 'shipped');
// several fields changed outside the grid (a form, a websocket)
const row = grid.getRowById('42');
Object.assign(row, { status: 'shipped', shippedAt: new Date() });
grid.refreshCells({ rows: [row], flash: true });
// …or, when the change can move the row (sort, filter): a transaction
grid.applyTransaction({ update: [{ id: 42, status: 'shipped' }] });| 하려는 일 | 쓸 것 |
|---|---|
| 사용자가 한 것처럼 셀 변경(실행 취소, 추적) | setCellValue |
| 직접 바꾼 행 객체 보여 주기 | refreshCells |
| 서버·실시간 변경, 행이 움직이거나 추가됨 | applyTransaction |
| 완전히 새 목록 | setData |
포커스 셀
| 이름 | 타입 | 설명 |
|---|---|---|
getFocusedCell() | { rowIndex, colId, row } | null | 키보드 포커스가 있는 셀과 그 행(그룹 행이면 row는 undefined). |
setFocusedCell(rowIndex, colId) | void | 셀에 포커스를 주고 보이게 스크롤한 뒤 키보드를 그리드로: 화살표, Enter, 입력이 거기서 이어짐. |
ensureCellVisible(rowIndex, colId?) | void | 셀이 보이게 스크롤. rowIndex가 null이면 옆으로만 스크롤해 컬럼을 보여 줌. |
// after adding a row, put the user on its first cell
const [row] = grid.addRows([{ id: 99 }], 0);
grid.setFocusedCell(grid.getRowIndex(row), 'name');
grid.startEdit(grid.getRowIndex(row), 'name');
// a toolbar button acting on the current row
button.onclick = () => {
const f = grid.getFocusedCell();
if (f?.row) openDetails(f.row);
};표시 위치는 정렬·필터·그룹, 서버 데이터의 스크롤에 따라 바뀝니다. id를 보관하고, 쓰기 직전에 getRowIndex로 위치를 구하세요.
이 페이지에 대한 질문
코드로 셀 하나를 바꾸되 실행 취소되게 하려면?
grid.setCellValue(행 또는 id, colId, 값)을 쓰세요. 편집처럼 기록되어 Ctrl+Z로 되돌릴 수 있고, 변경 표시가 생기며 cellValueChanged가 발생합니다. 규칙은 검사하지 않으니 필요하면 validateCell을 부르세요.
행 객체를 직접 바꿨는데 그리드가 안 바뀝니다.
그리드는 객체를 지켜보지 않습니다. grid.refreshCells({ rows: [row] })로 다시 그리거나(flash: true면 깜빡임), 정렬·필터까지 다시 돌리려면 applyTransaction({ update })로 보내세요.
보이는 순서대로 행을 받으려면?
grid.getDisplayedRows()는 정렬·필터 뒤의 데이터 행을 그룹 행 없이 돌려줍니다. forEachRow(fn, 'displayed')는 그 행들을, forEachRow(fn)은 데이터의 모든 행을 돕니다.