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 result = ref.current?.getValidResponse();
if (!result) return;
if (result.errors.length > 0) {
console.log('Validation errors:', result.errors);
return;
}
console.log('Valid responses:', result.response);
};

return (
<>
<EsheetRenderer ref={ref} formDataInput={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..."
}
}

Response Format Options

The renderer supports multiple output formats via the getResponse() method:

Native Format (Default)

Returns the raw FieldResponseMap — structured response objects keyed by field ID:

const response = ref.current?.getResponse();
// or explicitly:
const response = ref.current?.getResponse({ format: 'native' });

FHIR QuestionnaireResponse

Export responses directly as a FHIR R4 QuestionnaireResponse resource:

const fhirResponse = ref.current?.getResponse({
format: 'fhir',
fhir: {
questionnaireUrl: 'http://example.org/Questionnaire/my-form',
status: 'completed',
subject: { reference: 'Patient/123' },
author: { reference: 'Practitioner/456' },
},
});

// Returns:
// {
// resourceType: 'QuestionnaireResponse',
// questionnaire: 'http://example.org/Questionnaire/my-form',
// status: 'completed',
// subject: { reference: 'Patient/123' },
// author: { reference: 'Practitioner/456' },
// authored: '2024-01-15T10:30:00Z',
// item: [...]
// }

FHIR Options:

OptionTypeDescription
questionnaireUrlstringCanonical URL of the questionnaire (auto-detected if imported from FHIR)
statusstringResponse status: 'in-progress', 'completed', 'amended', 'entered-in-error'
subjectFhirReferencePatient/subject reference (e.g., { reference: 'Patient/123' })
authorFhirReferenceAuthor reference
resourceIdstringResource ID for the QuestionnaireResponse
tip

If the form was imported from a FHIR Questionnaire, the questionnaireUrl is automatically detected from the original resource metadata.

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}
formDataInput={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 getRawResponse() (or getValidResponse() for validated submission) for standard response collection.