이벤트
뷰어와 디자이너 이벤트 예제: onReady, onParamsSubmit, onPageChange, onError, onOutput, fetchData, onChange, onSave를 언제 어떻게 쓰는지 설명합니다.
이벤트로 뷰어와 디자이너의 동작에 맞춰 페이지가 반응하게 합니다. 옵션에 함수로 넘기며 모두 선택 사항입니다. 사용자가 보고서를 조회할 때 일어나는 순서대로 정리했습니다.
| 이벤트 | 어디 | 언제 |
|---|---|---|
onParamsSubmit(params) | viewer | 사용자가 조회를 누름. false면 머물고, 바꾼 조건을 돌려주면 그 값으로 조회. setParams()에는 불리지 않습니다. |
fetchData(params) | viewer | 행 불러오기: 처음, 조회, setParams() 때. { rows }(또는 Promise)를 돌려줍니다. |
onReady({ pages, rows, ms, params }) | viewer | 보고서를 다 만들어 보여 줌(실행할 때마다). |
onPageChange(page, total) | viewer | 보고 있는 페이지가 바뀜. |
onOutput(e) | viewer · createReport | 인쇄·파일 저장 직전(print, pdf, xlsx, xlsx-data, csv, hwpx). false면 취소. |
onError(error, during) | viewer | 실패: 'data', 'layout', 'output'. |
onChange(definition) | designer | 양식이 바뀔 때마다(실행 취소·다시 실행 포함). |
onSave(definition) | designer | 저장 버튼이나 Ctrl+S. |
뷰어 이벤트
조회 전에 조건을 검사하고, 조회가 끝나면 건수를 보여 주고, 페이지를 따라가고, 오류를 한곳에서 처리하고, 모든 출력을 기록하는 예입니다.
const viewer = createViewer(el, {
definition,
params: { from: '2026-10-01', to: '2026-10-31', dept: '' },
// 1. the user pressed 조회/Run: check or adjust the parameters first
onParamsSubmit: params => {
if (String(params.from) > String(params.to)) {
alert('시작일이 종료일보다 늦습니다.');
return false; // stay on the panel, nothing is loaded
}
return { ...params, dept: params.dept || myDept }; // or return changed parameters
},
// 2. load the rows for those parameters (start, 조회, setParams)
fetchData: params => fetch('/api/sales?' + new URLSearchParams(params as Record<string, string>)).then(r => r.json()),
// 3. after every successful run
onReady: ({ pages, rows, ms, params }) => {
summary.textContent = pages + '쪽 · ' + rows.toLocaleString() + '건 (' + ms + 'ms)';
printBtn.disabled = rows === 0;
},
// 4. the page in view changed (scroll, buttons, keyboard, goTo)
onPageChange: (page, total) => { pager.textContent = page + ' / ' + total; },
// 5. loading, layout, printing or saving failed (the viewer also shows a message)
onError: (error, during) => {
if (during === 'data' && /401/.test(error.message)) location.href = '/login';
else reportError(error); // your error tracker
},
// 6. before every print and file: log it, ask for a reason, or return false to block it
onOutput: async e => {
const reason = e.kind === 'print' ? prompt('출력 사유를 입력하세요') : '';
if (reason === null) return false;
await fetch('/api/report-logs', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ ...e, reason }) });
},
});- onParamsSubmit은 사용자가 조회를 누를 때만 불립니다. 코드에서 viewer.setParams()를 부르면 바로 fetchData로 갑니다.
- onReady는 처음 불러올 때와 조회, setData, setParams, setDefinition 뒤마다 불리므로 뷰어 바깥의 건수·버튼을 갱신하기 좋은 곳입니다.
- 이벤트 함수에서 오류가 나도 콘솔에만 남고 뷰어는 계속 동작합니다.
디자이너 이벤트
편집하는 동안 임시 저장하고, 서버에 저장하고, 저장하지 않고 떠날 때 경고하는 예입니다.
let dirty = false;
const designer = createDesigner(el, {
definition, data: { rows: sample },
// every change (move, resize, property, undo/redo): keep a draft, mark the page as changed
onChange: def => {
dirty = true;
localStorage.setItem('draft:sales', JSON.stringify(def));
},
// Ctrl+S or the Save button
onSave: async def => {
const res = await fetch('/api/reports/sales', { method: 'PUT', headers: { 'content-type': 'application/json' }, body: JSON.stringify(def) });
if (res.ok) { dirty = false; localStorage.removeItem('draft:sales'); }
},
});
addEventListener('beforeunload', e => { if (dirty) e.preventDefault(); }); // unsaved changes warningReact, Vue, Svelte, Angular에서
// React
<FreeReportViewer definition={def} fetchData={load} onReady={e => setCount(e.rows)} onPageChange={setPage} onError={showError} />
<!-- Vue -->
<FreeReportViewer :definition="def" :fetch-data="load" :on-ready="e => (count = e.rows)" :on-page-change="p => (page = p)" />
<!-- Svelte 5: onReady gives the viewer itself; the core onReady is onRendered -->
<FreeReportViewer {definition} fetchData={load} onRendered={e => (count = e.rows)} onPageChange={p => (page = p)} />
<!-- Angular: outputs -->
<free-report-viewer [definition]="def" [fetchData]="load" (rendered)="count = $event.rows" (pageChange)="page = $event.page" (error)="show($event.error)" />출력 이벤트(onOutput)로 출력 이력을 남기는 예는 따로 정리했습니다. 출력 이력