FreeGridv1.15.1English

서버 행 변경 반영

datasource에서 applyTransaction은 불러온 행을 그 자리에서 바꾸고(깜빡임), 추가·삭제는 기존 행을 보여 둔 채 불러온 블록을 다시 받습니다. refreshRows({ keepRows })로 직접 할 수도 있습니다.

실행 예제서버 행 변경

느린 가짜 서버의 행을 수정·추가·삭제.

이 데모의 코드
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;
}

datasource를 쓰면 행의 주인은 서버이고, 그리드는 불러온 블록만 가지고 있습니다. 서버에서 무언가 바뀌면(다른 사람의 수정, 내 저장 완료, 푸시 메시지) applyTransaction으로 그리드에 알려 주세요.

항목별 동작

트랜잭션datasource일 때
update같은 id(getRowId)의 불러온 행에 값을 덮어쓰고 바뀐 셀이 깜빡입니다. 불러오지 않은 행은 notFound에 담기고, 그 블록을 불러올 때 맞게 옵니다.
upsert불러온 행은 수정하고, 못 찾은 행이 있으면 새 행일 수 있으니 불러온 블록을 다시 요청합니다.
add / remove서버에서 이미 일어난 일이므로, 그리드가 불러온 블록을 다시 요청해 도착하면 바꿔 넣습니다. 그때까지 기존 행이 그대로 보여 로딩 행이나 화면 튐이 없습니다.
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

호출동작
refreshRows()모든 행을 잊고 보이는 곳부터 다시 불러옴. 그동안 로딩 행이 보임
refreshRows({ keepRows: true })불러온 블록만 다시 요청하고 답이 올 때까지 기존 행을 보여 줌

세부 동작

  • 결과는 datasource가 없을 때처럼 { added, updated, removed, notFound }이고 transactionApplied가 발생합니다.
  • 다시 받는 행에서 열려 있던 편집은 먼저 저장됩니다.
  • datasource 없이 쓰는 실시간 업데이트처럼, 트랜잭션은 실행 취소 대상이 아니고 사용자 수정(getModifiedRows)에 들어가지 않습니다.
  • setData, addRows, removeRows, 행 이동은 여전히 클라이언트 데이터 전용입니다. 서버를 바꾼 뒤 트랜잭션을 보내거나 refreshRows를 부르세요.
  • 사용자는 불러온 행의 셀을 편집할 수 있고, cellValueChanged나 getModifiedRows()로 저장하면 됩니다.

이 페이지에 대한 질문

무한 스크롤에서 전체를 다시 불러오지 않고 한 행만 바꾸려면?

그리드에 getRowId를 주고 applyTransaction({ update: [바뀐 행] })을 부르세요. 그 id의 불러온 행이 그 자리에서 바뀌며 깜빡이고, 아무것도 다시 받지 않습니다.