FreeGridv1.15.1한국어

Changes on server rows

With a datasource, applyTransaction updates loaded rows in place with a flash, and adds or removes reload the loaded blocks while the old rows stay on screen; refreshRows({ keepRows }) does it by hand.

Live demoServer row changes

Update, add and remove rows of a slow fake server.

Code for this demo
import { createGrid, type ColumnDef, type Row } 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 });
  // a fake server of 10,000 rows that answers in 600 ms
  let rows: Row[] = makeRows(10_000);
  const grid = createGrid(ctx.host, {
    columns: [{ field: 'id', header: 'ID', type: 'number', width: 80 }, { field: 'name', header: h('Name', '이름'), width: 170 }, { field: 'status', header: h('Status', '상태'), width: 120 }, { field: 'q1', header: h('Q1', '1분기'), type: 'number', format: '#,##0', width: 120 }],
    locale: ctx.lang, getRowId: r => String(r.id), blockSize: 100,
    datasource: { getRows: p => new Promise(res => setTimeout(() => res({ rows: rows.slice(p.start, p.end).map(r => ({ ...r })), total: rows.length }), 600)) },
  });
  grid.on('transactionApplied', e => ctx.log(`added ${e.added.length}, updated ${e.updated.length}, removed ${e.removed.length}, notFound ${e.notFound.length}`));
  button(ctx, h('Server changes row 2', '서버에서 2행 변경'), () => {
    const r = rows.find(x => x.id === 2)!;
    r.status = r.status === 'Active' ? 'Pending' : 'Active';
    r.q1 = Math.round(Math.random() * 100000);
    grid.applyTransaction({ update: [{ ...r }] });
  });
  button(ctx, h('Server deletes the first row', '서버에서 첫 행 삭제'), () => {
    const gone = rows.shift()!;
    grid.applyTransaction({ remove: [{ id: gone.id }] });
  });
  button(ctx, h('Server adds a row at the top', '서버에서 맨 위에 행 추가'), () => {
    const r = { ...rows[0], id: 100000 + rows.length, name: h('New customer', '새 고객') };
    rows = [r, ...rows];
    grid.applyTransaction({ add: [r] });
  });
  button(ctx, h('Reload, keep rows', '행 유지하며 다시 받기'), () => grid.refreshRows({ keepRows: true }));
  text(ctx, h('Updates change in place with a flash. Deletes and adds reload the loaded blocks; the old rows stay until the answer (0.6 s).',
    '수정은 그 자리에서 깜빡이며 바뀝니다. 삭제·추가는 불러온 블록을 다시 받고, 답(0.6초)이 올 때까지 기존 행이 그대로 보입니다.'));
  return grid;
}

With a datasource the server owns the rows; the grid only holds the blocks it has loaded. When something changes on the server — someone else edited a row, your own save finished, a push message arrived — tell the grid with applyTransaction.

What each part does

TransactionWith a datasource
updateFields are copied onto the loaded row with the same id (getRowId); the changed cells flash. Rows that are not loaded are listed in notFound — they will come right when their block is loaded.
upsertUpdates loaded rows; if some were not found, the loaded blocks are asked for again (they may be new).
add / removeHappened on the server already: the grid asks again for the blocks it has loaded and swaps them in when they arrive. Until then the old rows stay on screen — no loading rows, no jump.
const grid = createGrid(el, {
  columns,
  getRowId: row => String(row.id),        // needed to find rows by id
  datasource: { getRows: params => fetch('/api/orders?' + toQuery(params)).then(r => r.json()) },
});

// a websocket says order 42 changed
socket.on('order', o => grid.applyTransaction({ update: [o] }));

// your own delete finished on the server
await fetch('/api/orders/7', { method: 'DELETE' });
grid.applyTransaction({ remove: [{ id: 7 }] });   // the loaded blocks reload; rows stay until then

// after a bulk import: the same by hand
grid.refreshRows({ keepRows: true });

refreshRows

CallDoes
refreshRows()Forgets every row and loads from the start of the view; rows show as loading meanwhile
refreshRows({ keepRows: true })Asks again only for the loaded blocks and keeps them on screen until the answers come

Details

  • The result is { added, updated, removed, notFound } and transactionApplied fires, as without a datasource.
  • An edit open in a reloaded row is saved first.
  • Transactions are not undoable and do not count as user edits (getModifiedRows), like live updates without a datasource.
  • setData, addRows, removeRows and row moves stay client-only: change the server, then send a transaction or call refreshRows.
  • Users can still edit cells of loaded rows; save them with cellValueChanged or getModifiedRows().

Questions about this page

How do I update one row in infinite scroll without reloading everything?

Call applyTransaction({ update: [changedRow] }) with a getRowId on the grid. The loaded row with that id changes in place and flashes; nothing is fetched.