View field
Introduction
Section titled “Introduction”ViewField is the escape hatch for read-only custom markup inside a schema. .content() accepts a string or callable evaluated with state and render context. Defaults _dehydrated = False. Content is inserted into or-view-field without automatic escaping when you return HTML from a callable — sanitize untrusted data yourself. For interactive controls, subclass Field instead (see Custom fields).
Each variation below includes a detailed explanation, the fluent API to paste into your schema, and light/dark screenshots of the rendered control.
Basic view field
Section titled “Basic view field”Static HTML summary with a label.
ViewField.make('summary') .label('Summary') .content('<strong>3</strong> open invoices')

Callable content
Section titled “Callable content”Build markup from record/state at render time. Return a safe HTML string.
ViewField.make('balance') .label('Balance') .content(lambda state=None, record=None, **_: f'<span class="or-money">{state or 0}</span>')

Hidden when empty
Section titled “Hidden when empty”Use .visible() closures to omit the field when there is nothing to show.
ViewField.make('warning') .label('Warning') .content(lambda record=None, **_: getattr(record, 'warning_html', '')) .visible(lambda record=None, **_: bool(getattr(record, 'warning_html', None)))

Dehydrated view value
Section titled “Dehydrated view value”If you need the view payload in dehydrated state (for example a signed summary string), opt into dehydration.
ViewField.make('checksum') .label('Checksum') .content(lambda state=None, **_: state or '') .dehydrated(True)

Closures work on .label(), .helper_text(), .placeholder(), .visible(), .disabled(), and .required() where applicable — see Form closures.