Skip to content

toField

toField turns a V0 question into a Field: the control to render and its constraints.

const field = toField(question, options?)
import { toField } from '@partner-sdk/core/view-model';
const field = toField(state.questions[name]);
  • question: a Question from state.questions or q.questions.
  • options.now (optional): fixes relative date bounds. Default Date.now().

A Field. Every field has:

  • name: key for session.edit and fieldState.
  • field: the submit key.
  • label, hint?: HTML.
  • required.
  • invalidMessage?: the question’s own error copy.
  • commit: "blur" | "change" | "none": when to call session.flush().

Plus, by kind:

kind Extra fields
text format (text, email, tel, zip), inputType, autoComplete?, inputMode?, minLength?, maxLength?, pattern?, placeholder?
number prefix? ("$"), min?, max?, integer
date min?, max? (YYYY-MM-DD)
choice options ({ value, label }[]), presentation (radio for 4 or fewer, else select)
multi options, presentation (group or checkbox), description?
search search: the trade search template
info
  • Cached per question object, so the result is referentially stable.
  • Unknown question types fall back to text.

Converts a UI value to a wire value: strips , $ and spaces from currency, phones to E.164, trims zips. The session calls this for you; use it only with the raw client.

const renderers: Record<Field['kind'], (f: any) => HTMLElement> = {
text: TextInput,
number: NumberInput,
date: DateInput,
choice: (f) => (f.presentation === 'radio' ? RadioGroup(f) : Select(f)),
multi: CheckboxGroup,
search: TradeSearch,
info: InfoBlock,
};
const el = renderers[field.kind](field);

Labels and hints are HTML. Render them as HTML (sanitised by your framework or a Trusted Types policy), not as text.