Skip to main content

Collecting & Pre-filling Responses

This guide covers how to collect form responses from the renderer and how to pre-fill forms with existing data.

Collecting Responses

Via Ref API

The primary way to get responses is through the imperative ref:

import { useRef } from 'react';
import { EsheetRenderer } from '@esheet/renderer';
import type { EsheetRendererHandle } from '@esheet/renderer';

function MyForm() {
const ref = useRef<EsheetRendererHandle>(null);

const handleSubmit = () => {
const responses = ref.current?.getResponse();
if (!responses) return;

// responses is Record<string, FieldResponse>
console.log(responses);
};

return (
<>
<EsheetRenderer ref={ref} formData={myForm} />
<button onClick={handleSubmit}>Submit</button>
</>
);
}

Response Shape by Field Type

Field TypeResponse PropertyShape
text, longtextanswerstring
radio, dropdown, boolean, rating, sliderselectedSelectedOption ({ id, value })
check, multiselectdropdown, rankingselectedSelectedOption[]
multitextmultitextAnswersRecord<optionId, string>
singlematrixselectedRecord<rowId, SelectedOption>
multimatrixselectedRecord<rowId, SelectedOption[]>
signaturesignatureData, signatureImageStroke JSON, base64 PNG
diagrammarkupData, markupImageStroke JSON, base64 PNG
display, html, image, section--No response (presentational)

Full Example Response

{
"patient_name": {
"answer": "Jane Doe"
},
"visit_reason": {
"selected": { "id": "opt2", "value": "Follow-up" }
},
"symptoms": {
"selected": [
{ "id": "s1", "value": "Headache" },
{ "id": "s3", "value": "Fatigue" }
]
},
"vitals": {
"multitextAnswers": {
"bp": "120/80",
"hr": "72"
}
},
"severity_matrix": {
"selected": {
"row_head": { "id": "col_mild", "value": "Mild" },
"row_back": { "id": "col_severe", "value": "Severe" }
}
},
"patient_signature": {
"signatureData": "[{\"points\":[{\"x\":0.1,\"y\":0.2}...]}]",
"signatureImage": "data:image/png;base64,iVBOR..."
}
}

Pre-filling Responses

Pass initialResponses to populate the form with existing data:

const existingResponses = {
patient_name: { answer: 'Jane Doe' },
visit_reason: { selected: { id: 'opt2', value: 'Follow-up' } },
};

<EsheetRenderer
ref={ref}
formData={myForm}
initialResponses={existingResponses}
/>;

This is useful for:

  • Editing previously submitted forms
  • Resuming partially completed forms
  • Displaying read-only form data (combine with disabled styling)

Hydrating Responses

To create a human-readable export that joins questions with answers, use hydrateResponse() from @esheet/core:

import { hydrateResponse } from '@esheet/core';

const handleExport = () => {
const formStore = ref.current?.getFormStore();
if (!formStore) return;

const state = formStore.getState();
const hydrated = state.hydrateResponse();
// hydrated includes both question text and answer values
};

Direct Store Access

For advanced scenarios, access the underlying stores:

const formStore = ref.current?.getFormStore();
const uiStore = ref.current?.getUIStore();

// Read state
const state = formStore.getState();
const allResponses = state.responses;
const specificField = state.getField('field_id');
const fieldResponse = state.getResponse('field_id');

// Check conditional states
const isVisible = state.isVisible('field_id');
const isEnabled = state.isEnabled('field_id');
const isRequired = state.isRequired('field_id');
warning

Direct store access is an advanced API. The store's internal structure may change between versions. Prefer using getResponse() for standard response collection.