Skip to content

Field types ​

Every field is a subtype of the sealed FormFieldDefinition. A switch over a field is exhaustive, and each subtype's copyWith returns its own concrete type.

Shared options ​

Every field type accepts these parameters.

ParameterTypeMeaning
keyStringRequired. Stable value key, unique in the form. Values, rules and formulas ($key) use it.
labelStringRequired, non-blank.
descriptionString?A sentence under the label saying what the field is for.
hintString?Example text inside an empty input.
helpTextString?Longer guidance behind the field's info button.
requiredboolAdds a RequiredValidation at index 0 of validations. The required getter reads it back.
readOnlyboolThe field can't be edited, whatever rules enable. A value a rule sets also shows read-only. It shows as CdxAccess.readOnly: fully legible, never dimmed (see Access).
validationsIterable<FormValidation>Ordered list of rules. See Validation.

On copyWith, null keeps a text value and a blank string clears description, hint or helpText. copyWith(required: ...) adds or removes only the required rule.

dart
final withHelp = field.copyWith(helpText: 'One line; details go in What happened.');
final optional = field.copyWith(required: false);

Built-in types ​

ClassJSON typeOwn optionsValue
TextFormFieldtextinputKind: TextInputKind (singleLine, multiline, richText, masked)String
NumberFormFieldnumberdecimal: bool. Bounds come from NumericRangeValidation.int, or Rational when decimal
MoneyFormFieldmoneydefaultCurrency: String?MoneyValue(amount, currency)
QuantityFormFieldquantitydimension: String?, units: Iterable<String> (the first is the default; empty means the host's unit lookup offers them)QuantityValue(amount, unit)
DurationFormFielddurationnoneDuration
ToggleFormFieldbooleandisplay: ToggleDisplay (toggle, a switch; or checkbox)bool
ChoiceFormFieldchoicechoices: Iterable<FormChoice> (required), multiple: bool, display: ChoiceDisplay (dropdown; radio, every option as a radio button or, for several, a checkbox; or chips)String, or Set<String> when multiple
ReferenceFormFieldreferencetarget: String (a host entity type id, required), multiple: bool, scan: bool (a camera button beside the lookup; see Barcode scanning)record id(s)
RatingFormFieldratingmaxStars: int (default 5, at most 10)int from 1 to maxStars; null for no rating
DateTimeFormFielddateTimekind: TemporalKind (date, time, dateTime); shorthand dateOnly: trueDateTime
DateRangeFormFielddateRangenoneDateRangeValue(start, end)
DateTimeRangeFormFielddateTimeRangenoneDateTimeRangeValue(start, end)
AttachmentFormFieldattachmentimagesOnly: bool, multiple: boolAttachmentValue, or List<AttachmentValue> when multiple
SignatureFormFieldsignaturemeaning: FormSignatureMeaning (author, reviewer, approver, witness; default author), remarks: FormSignatureRemarks (hidden, optional, required; default hidden), signLabel: String? (the button text, Sign by default), statement: String? (what the signer declares)SignatureValue; null while unsigned
FormulaFormFieldformulaexpression: String, outputType: ValueType (both required). Always read-only; has no required or readOnly parameter.computed
CustomFormField<T>your typeIdtypeId, configuration: T, configurationVersion (default 1)yours

Minimum sizes for each type are listed on the Layout page.

Choices ​

dart
ChoiceFormField(
  key: 'severity',
  label: 'Severity',
  required: true,
  choices: const [
    FormChoice(value: 'minor', label: 'Minor'),
    FormChoice(value: 'major', label: 'Major'),
    FormChoice(value: 'critical', label: 'Critical'),
  ],
)

Choice values must be non-blank and unique; labels must be non-blank.

Attachments ​

An attachment's value is an AttachmentValue: the host's reference to the stored file, its name, mediaType and bytes, and sha256, the lowercase hex SHA-256 of the file's bytes (null for a reference the host stored itself and whose bytes the form never saw). The form carries references, never bytes. toJson and AttachmentValue.fromJson write and read it; a checksum that isn't 64 lowercase hex digits is refused.

An image the host can show is a thumbnail that opens a large preview; every other file is a chip that opens the host's viewer, if it has one. Size, count and media-type limits are an AttachmentValidation on the field. See Host services.

Signatures ​

A signature field holds an electronic signature the host recorded after checking the signer's credentials. Unsigned it shows a Sign button; signed, a receipt that says who signed as what, and when. The value is a SignatureValue and carries no secret:

MemberMeaning
signerId, signerNameWho signed, as the host knows them.
meaningWhat the signature attests (FormSignatureMeaning). A field accepts only its own.
signedAtWhen, always in UTC.
methodHow the signer proved who they are: FormSignatureMethod.password or pin.
receiptIdThe host's id of its own record of the signature (an assertion or signature id).
reasonThe signer's reason or remarks, when asked for and given.
contentDigestThe SHA-256, as lowercase hex, the host computed over what was signed.

The field never sees a password or a PIN; FormSignatureService is the host's side of the ceremony. A required signature field must be signed to validate; SignatureValidation ("signed") asks the same of an optional one, or when a rule applies it. A value signed as another meaning, or without the reason a field asks for, fails validation. Rules read a signature only as empty or not empty. See Signatures for the service and what it must do.

Host services ​

Some types need the host. FormHostServices holds a hook for each, which the host gives once to a KitScope<FormKit>; Host services describes them all, and vyuh_form_kit_capture implements the camera and file ones.

FieldFormHostServices memberSignature
ReferenceFormFieldreferenceSearchFuture<List<FormChoice>> Function(String target, String query, int pageSize)
ReferenceFormFieldreferenceLabelFuture<String?> Function(String target, String value)
ReferenceFormField (scan)referenceScanner, referenceScanResolverFuture<String?> Function(BuildContext, ReferenceFormField), and Future<FormChoice?> Function(String target, String scanned)
MoneyFormField, QuantityFormFieldcodeSearchFuture<List<FormChoice>> Function(String catalog, String? dimension, String query, int pageSize) (catalog is currency or unit)
AttachmentFormFieldattachmentPicker, attachmentImage, attachmentPreviewFuture<List<AttachmentValue>?> Function(BuildContext, AttachmentFormField field, List<AttachmentValue> current) (null when the user cancels); ImageProvider? Function(AttachmentValue); Future<void> Function(BuildContext, AttachmentValue)
SignatureFormFieldsignatureService, signatureDigesta FormSignatureService, and String? Function(FormKitForm)
CustomFormField, CustomContentthe kit's view parts, not a servicetype.withParts(view: ViewPart<CustomFieldInput<C>>((context, input) => …)), and ViewPart<CustomContent<C>> for content; see Custom fields

Formula fields ​

dart
FormulaFormField(
  key: 'line_cost',
  label: 'Line cost',
  expression: r'$qty * $unit_cost',
  outputType: ValueType.rational, // re-exported by vyuh_form_types
)

A formula declares no dependency list: its inputs come from compiling the expression against the fields in its scope. See Rules and formulas.

Content nodes ​

Content is not a field and has no value. It sits in the layout tree wherever a field slot can.

ClassJSON typeOptionsRendered by
CalloutContentcallouttitle (optional plain text), body (inline rich text), variant: CalloutVariant (neutral, info, success, warning, critical; default info), showIcon, showBorder (both default true)FormView, as a CDX Banner
ImageContentimageimage (the asset reference, null until chosen), altText, width: ImageWidth (fill or fixed(px)), height: ImageHeight (auto or fixed(px)), fit: ImageFit (contain, cover), align: ImageAlign (start, center, end)KitScope<FormKit>(services: FormHostServices(assets:))
DividerContentdividernoneFormView
SpacerContentspacergridUnits (at least 1)FormView
CustomContent<T>customtypeId, configuration: T, configurationVersionNo renderer yet: FormView shows an "Unsupported content" placeholder

The codec leaves out callout and image settings at their defaults, so a plain callout is {"type": "callout", "body": "…"}. A fixed width or height is written as its pixels; fill and auto are left out.

Callout ​

A callout's body is inline rich text: **bold**, *italic*, `code`, ==highlight==, ~~strike~~, ++underline++, ^super^, ~sub~ and [text](url). It renders through the CDX RemarksText, and the callout itself as a CDX Banner of its variant, so the designer's canvas and the filled form look the same.

Image ​

An image refers to its picture by the reference the host's FormAssetProvider returned:

dart
abstract interface class FormAssetProvider {
  Future<String?> pick(BuildContext context, {required Set<String> mediaTypes});
  ImageProvider image(String ref);
}

The designer calls pick when the author chooses a picture; FormView and the canvas call image to load it. Give the provider once, as FormHostServices(assets:) in the KitScope<FormKit>; FormView and FormKitEditor both take it from there. package:vyuh_form_kit/testing.dart has MemoryAssetProvider, which keeps what an injected picker returns in memory under mem:<n> references.

Outside a grid an image is its width (the container's, or fixed pixels no wider than the container) and its height (the picture's aspect ratio, or fixed pixels). In a grid its placement is its box, and its own width and height don't apply (fillsGridBox). Fit and align place the picture in its box. With no picture chosen, or no provider, the form shows a placeholder saying so; if the picture fails to load, its alt text.

Coming later ​

Text formats (email, phone, URL) with implicit validation, input masks and sliders are planned. See the Roadmap.