FreeGridv1.15.1한국어

Finding and changing rows in code

getRowById, getRowIndex, getDisplayedRows, forEachRow, getCellValue, setCellValue, refreshCells, getFocusedCell and setFocusedCell: read and change rows and cells without reloading the data.

Live demoRow API

Find a row by id, change one cell, repaint, move the focus.

Code for this demo
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;
}

Most changes go through the data: setData for a new list, applyTransaction for rows that changed. For the small things in between — read the row the user is on, change one cell, find where a row is shown — use these methods. Rows are found by the id from getRowId, so set it.

Finding rows

NameTypeDescription
getRowById(id)Row | undefinedThe row with this id, shown or filtered out. Server data: loaded rows only.
getRowIndex(rowOrId)numberWhere the row is shown after sorting, filtering and grouping; -1 when it is not shown. Use it with scrollToRow and setFocusedCell.
getDisplayedRowAt(index)Row | undefinedThe data row at a display index; undefined for group, detail and not-yet-loaded rows.
getDisplayedRows()Row[]Data rows in the order shown, group rows left out.
forEachRow(fn, scope?)voidfn(row, index) for every row of the data ('all', default, in data order) or every shown data row ('displayed').
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');

Reading and changing cells

NameTypeDescription
getCellValue(rowOrId, colId)unknownThe value as the grid reads it: valueGetter, nested field, formula result.
setCellValue(rowOrId, colId, value)booleanWrite one cell like an edit: undo, change mark, dependent columns cleared, cellValueChanged. Not checked against the rules. False when the row or column is not found or the value is the same.
refreshCells({ rows?, colIds?, flash? })voidRepaint after you changed row objects yourself: the given rows (or ids), or every row. flash marks the cells like a live update. Sorting and filters are not run again.
// 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' }] });
You wantUse
Change a cell as if the user did (undo, tracked)setCellValue
Show changes you made to row objectsrefreshCells
Server or live changes; rows may move or be addedapplyTransaction
A whole new listsetData

The focused cell

NameTypeDescription
getFocusedCell(){ rowIndex, colId, row } | nullThe cell with the keyboard focus and its row (row is undefined on a group row).
setFocusedCell(rowIndex, colId)voidFocus a cell, scroll it into view and give the grid the keyboard: arrows, Enter and typing go on from there.
ensureCellVisible(rowIndex, colId?)voidScroll a cell into view; with rowIndex null only sideways, to show a column.
// 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);
};

Display indexes change with sorting, filtering, grouping and scrolling in server data. Keep ids, and turn them into an index (getRowIndex) right before you use it.

Questions about this page

How do I change one cell from code so it can be undone?

grid.setCellValue(rowOrId, colId, value). It is recorded like an edit: Ctrl+Z undoes it, the cell is marked as changed and cellValueChanged fires. Rules are not checked; call validateCell when you need them.

I changed a row object myself and the grid did not update. What now?

The grid does not watch your objects. Call grid.refreshCells({ rows: [row] }) to repaint them (add flash: true to show it), or send the change with applyTransaction({ update }) so sorting and filters run again.

How do I get the rows in the order they are shown?

grid.getDisplayedRows() returns the data rows after sorting and filtering, group rows left out. forEachRow(fn, 'displayed') walks them; forEachRow(fn) walks every row of the data.