Skip to main content

Quick Start: Renderer

Render a form and collect user responses in your React application.

Choose Your Integration

Use casePackage
React app@esheet/renderer (this page)
Non-React / plain JS@esheet/renderer-standalone
Meteor Blaze@esheet/renderer-blaze

YAML is eSheet's canonical format for committed form layouts. You can also pass plain objects or JSON strings, and the renderer auto-detects both serialization formats.

Basic Example

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

const myForm = `
id: feedback-survey
title: Feedback Survey
pages:
- id: feedback
fields:
- id: name
fieldType: text
question: Your Name
required: true
inputType: string
- id: rating
fieldType: rating
question: How would you rate our service?
options:
- id: r1
value: '1'
- id: r2
value: '2'
- id: r3
value: '3'
- id: r4
value: '4'
- id: r5
value: '5'
- id: comments
fieldType: longtext
question: Additional Comments
`;

function App() {
const rendererRef = useRef<EsheetRendererHandle>(null);

const handleSubmit = () => {
const result = rendererRef.current?.getValidResponse();
if (!result) return;

if (result.errors.length > 0) {
console.log('Validation errors:', result.errors);
return;
}

console.log('Valid form responses:', result.response);
};

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

Collecting Responses

The renderer exposes an imperative API via ref:

const ref = useRef<EsheetRendererHandle>(null);

// Get all responses
const responses = ref.current?.getRawResponse();
// => { name: { answer: 'John' }, rating: { selected: { id: 'r4', value: '4' } }, ... }

// Access the underlying stores (advanced)
const formStore = ref.current?.getFormStore();
const uiStore = ref.current?.getUIStore();

Response Shape

Responses are typed as FormResponse = Record<string, FieldResponse>, where each key is a field ID:

interface FieldResponse {
answer?: string; // text, longtext
selected?: // radio, dropdown, boolean, rating, slider,
| SelectedOption // check, multiselectdropdown, ranking
| SelectedOption[] // (SelectedOption = { id, value })
| Record<string, SelectedOption | SelectedOption[]>; // matrix
multitextAnswers?: Record<string, string>; // multitext
signatureData?: string; // signature (stroke data)
signatureImage?: string; // signature (base64 PNG)
markupData?: string; // diagram (stroke data)
markupImage?: string; // diagram (base64 PNG)
}

Pre-filling Responses

Pass initialResponses to pre-populate the form:

<EsheetRenderer
ref={rendererRef}
formDataInput={myForm}
initialResponses={{
name: { answer: 'Jane Doe' },
rating: { selected: { id: 'r4', value: '4' } },
}}
/>

Accepting YAML/JSON Strings

The renderer accepts form definitions as objects, YAML strings, or JSON strings. YAML is the recommended format for committed definitions:

// YAML string
<EsheetRenderer formDataInput={yamlString} />

// JSON string for wire/API interchange
<EsheetRenderer formDataInput='{"id":"my-form","pages":[]}' />

Props

PropTypeDefaultDescription
formDataInputFormDefinition | stringrequiredForm definition (object, YAML, JSON, FHIR, MCP, SurveyJS)
classNamestring''Additional CSS class for the root
initialResponsesFormResponse--Pre-fill response data
allowDangerousJSbooleanfalseAllow JS calculations and conditionType: 'js'
strictbooleanfalseRequire a native eSheet FormDefinition; skip auto-detection
onReady() => void--Called when the form definition is loaded
touchModeboolean | 'auto'--Touch mode: true, false, 'auto', or omit for CSS
onTouchModeChange(enabled: boolean) => void--Callback when touch mode changes
onRendererToolsReady(tools: RendererTools) => void--Called with MCP tool handler when ready
refRef<EsheetRendererHandle>--Imperative handle for response collection

Ref API (EsheetRendererHandle)

MethodReturnsDescription
getRawResponse()FormResponseCurrent response values for all fields
getResponse(options?)FormResponse | FhirQuestionnaireResponseResponses in native or FHIR format
getValidResponse(){ response: FormResponse | null, errors: ValidationError[] }Validate + get responses
getFormStore()FormStoreThe underlying form state store
getUIStore()UIStoreThe underlying UI state store
isTouchModeEnabled()booleanCheck if touch mode is currently enabled
setTouchMode(enabled)voidManually enable/disable touch mode
resetTouchMode()voidReset to auto-detection (when touchMode="auto")

What's Next