RenderersLast updated on
Last updated on
Render artifacts to different output formats
Renderers transform OpenForm artifacts into output formats like text, PDF, and DOCX. Each renderer implements the OpenFormRenderer interface, making it easy to build custom renderers for your specific needs.
Installation
Install all renderers via the umbrella package:
npm install @open-form/renderersOr install individual renderer packages:
npm install @open-form/renderer-text
npm install @open-form/renderer-pdf
npm install @open-form/renderer-docxUsage
import { textRenderer } from '@open-form/renderers'
// Or from individual package:
// import { textRenderer } from '@open-form/renderer-text'
import { open } from '@open-form/core'
// Create a form with a template layer
const form = open.form({
name: 'invoice',
fields: {
customer: { type: 'text', label: 'Customer' },
total: { type: 'money', label: 'Total' }
},
layers: {
text: {
kind: 'inline',
mimeType: 'text/plain',
text: 'Invoice for {{customer}}\nTotal: {{total}}'
}
},
defaultLayer: 'text'
})
// Fill the form with data
const filled = form.fill({
fields: {
customer: 'Acme Corp',
total: { amount: 1500, currency: 'USD' }
}
})
// Render the filled form
const output = await filled.render({
renderer: textRenderer()
})
// output: "Invoice for Acme Corp\nTotal: $1,500.00"Renderer Packages
| Package | Description |
|---|---|
| Text | Handlebars-based text templating for HTML, Markdown, plain text |
| Fill PDF forms with AcroForm field support | |
| DOCX | Generate Word documents from templates |
Renderer Interface
All renderers implement the OpenFormRenderer interface. Use this to build custom renderers:
import type { OpenFormRenderer, RenderRequest, RendererLayer } from '@open-form/types'
const myRenderer: OpenFormRenderer<RendererLayer, string> = {
id: 'my-renderer',
render(request: RenderRequest): string {
const { template, form, data, bindings, ctx } = request
// Your rendering logic here
return processTemplate(template.content, data)
}
}OpenFormRenderer
id: string
Unique identifier for this renderer (e.g., "text", "pdf", "docx")
Methods
render: (request: RenderRequest) => Output | Promise<Output>
Execute the rendering operation
RenderRequest
The request object passed to the render method:
template: RendererLayer
The resolved template layer to render
form: Form
The form schema (used for field type detection)
data: FormData
The data to populate the template with
bindings?: Bindings
Optional mapping from template placeholders to field names
ctx?: OpenFormRendererContext
Optional context with locale, logger, serializers
RendererLayer
The resolved template content:
type: "text" | "docx" | "pdf" | string
Logical template type
content: string | Uint8Array
Template payload (text or binary)
mimeType?: string
Media type (e.g., "text/html", "application/pdf")
bindings?: Bindings
Template-specific field mappings
OpenFormRendererContext
Optional context for customizing renderer behavior:
locale?: string
Locale for formatting (e.g., "en-US")
logger?: { debug?, info?, warn?, error? }
Logger instance for debugging
serializers?: SerializerRegistry
Custom formatters for field values
Building Custom Renderers
To create a custom renderer:
- Implement the
OpenFormRendererinterface - Handle the template type(s) you support
- Use serializers for consistent value formatting
import type { OpenFormRenderer, RenderRequest, RendererLayer } from '@open-form/types'
// Custom CSV renderer example
export function csvRenderer(): OpenFormRenderer<
RendererLayer & { type: 'text'; content: string },
string
> {
return {
id: 'csv',
render(request: RenderRequest) {
const { form, data } = request
// Generate CSV from form fields and data
const headers = Object.keys(form.fields || {})
const values = headers.map(key => {
const value = data.fields?.[key]
return value != null ? String(value) : ''
})
return [headers.join(','), values.join(',')].join('\n')
}
}
}Related
- Serialization - Value formatting for renderers
- Form Layers - Template layer configuration