Field Types
The form system includes 12 built-in field types. Every field extends the abstract FormField base class and creates a typed FormControl for the reactive_forms FormGroup.
Base: FormField
All fields share these properties from FormField:
abstract class FormField extends ContentItem {
final String title; // Display label
final String name; // Unique field identifier
final String? placeholder; // Hint text
final String? help; // Helper text below the field
final Object? initialValue; // Initial value
final List<ValidationConfiguration>? validations;
final List<AsyncValidationConfiguration>? asyncValidations;
final List<FormFieldRule> rules;
// Observable state (not serialized)
late final Observable<bool> isVisible;
late final Observable<bool> isEnabled;
DynamicValidator? dynamicValidator;
}Field width is not configured on FormField. Use a runtime FormRowBlock or the visual editor's RowInstance when fields need explicit 12-column row spans. Ordinary fields can live directly in Form.items, section items, or repeating-section templates.
TextField
Standard text input with secure mode, formatter mask, and multiline support.
TextField(
name: 'student_name',
title: 'Student Name',
placeholder: 'Enter your full name',
help: 'As it appears on your ID',
isSecure: false, // Password mode
formatterMask: null, // Input mask pattern
maxLines: null, // Multiline (e.g., 3 for textarea)
maxLength: null, // Character limit
validations: [RequiredValidation(errorMessage: 'Name is required')],
)Control type: FormControl<String>
DSL:
FormBuilder(title: 'Form')
.text('student_name', title: 'Student Name')
.required('Name is required')
.placeholder('Enter your full name')
.help('As it appears on your ID')
.secure() // Password mode
.multiline(3) // Textarea with 3 lines
.charLimit(200) // Max character length
.mask('###-##-####') // Input formatter maskNumberField
Numeric input with decimal/integer toggle.
NumberField(
name: 'capacity',
title: 'Capacity',
allowDecimal: true, // false for integer-only
validations: [NumberRangeValidation(min: 1, max: 500, errorMessage: '...')],
)Control type: FormControl<num>
DSL:
.number('capacity', title: 'Capacity')
.decimal() // Allow decimals (default)
.integerOnly() // Integer only
.range(min: 1, max: 500)
.min(1)
.max(500)SelectField
Dropdown with flat options, grouped options, and multi-select support.
SelectField(
name: 'course',
title: 'Course',
options: [
SelectOption(value: 'flutter_101', title: 'Flutter 101'),
SelectOption(value: 'dart_adv', title: 'Advanced Dart'),
SelectOptionGroup(title: 'Specializations', options: [
SelectOption(value: 'mobile', title: 'Mobile Dev'),
SelectOption(value: 'web', title: 'Web Dev'),
]),
],
allowMultiple: false,
validations: [RequiredValidation(errorMessage: 'Select a course')],
)Control type: FormControl<String> (single) or FormControl<List<String>> (multi)
Layouts: DefaultSelectFieldLayout, SelectFieldDialogLayout
DSL:
.select('course', title: 'Course')
.option('flutter_101', title: 'Flutter 101')
.option('dart_adv', title: 'Advanced Dart')
.options({'mobile': 'Mobile Dev', 'web': 'Web Dev'})
.optionGroup('Specializations', [...])
.multiple()
.required()BooleanField
Checkbox or switch toggle with optional tristate (true/false/null).
BooleanField(
name: 'agree_terms',
title: 'I agree to the terms',
tristate: false,
validations: [RequiredValidation(errorMessage: 'You must agree')],
)Control type: FormControl<bool>
Layouts: SwitchBooleanFieldLayout (default), CheckboxBooleanFieldLayout
DSL:
.boolean('agree_terms', title: 'I agree to the terms')
.tristate()
.required()DateTimeField
Date, time, or combined date-time picker.
DateTimeField(
name: 'start_date',
title: 'Start Date',
selectionType: SelectionType.date, // date, time, dateTime
validations: [
RequiredValidation(errorMessage: 'Date is required'),
FutureDateValidation(maxFutureDays: 90, errorMessage: 'Max 90 days ahead'),
],
)Control type: FormControl<DateTime>
SelectionType values: date, time, dateTime
DSL:
.dateTime('start_date', title: 'Start Date')
.dateOnly() // SelectionType.date
.timeOnly() // SelectionType.time
.dateAndTime() // SelectionType.dateTime (default)
.required()SliderField
Single-value slider with configurable range and divisions.
SliderField(
name: 'rating',
title: 'Course Rating',
min: 1,
max: 5,
divisions: 4,
)Control type: FormControl<double>
DSL:
.slider('rating', title: 'Course Rating',
min: 1, max: 5, divisions: 4)RangeSliderField
Dual-thumb range slider for selecting a min/max range.
RangeSliderField(
name: 'price_range',
title: 'Price Range',
min: 0,
max: 1000,
divisions: 20,
)Control type: FormControl<RangeValues>
PhoneNumberField
Phone number input with filtered keyboard and formatting.
PhoneNumberField(
name: 'phone',
title: 'Phone Number',
placeholder: '+1-555-0100',
validations: [RequiredValidation(errorMessage: 'Phone is required')],
)Control type: FormControl<String>
DSL:
.phone('phone', title: 'Phone Number')
.required()ImagePickerField
Image selection from device gallery with multi-image support.
ImagePickerField(
name: 'profile_photo',
title: 'Profile Photo',
maxImages: 1,
validations: [RequiredValidation(errorMessage: 'Photo is required')],
)Control type: FormControl<List<XFile>?>
DSL:
.image('profile_photo', title: 'Profile Photo')
.required()FilePickerField
File selection with extension filtering.
FilePickerField(
name: 'transcript',
title: 'Upload Transcript',
allowedExtensions: ['pdf', 'doc', 'docx'],
)Control type: FormControl<List<PlatformFile>?>
DSL:
.file('transcript', title: 'Upload Transcript')FormulaField
Computed/derived field that evaluates expressions from other field values.
FormulaField(
name: 'total_cost',
title: 'Total Cost',
formula: 'course_fee * (1 + tax_rate / 100)',
resultType: FormulaResultType.number,
numberFormat: '#,##0.00',
prefix: '\$',
errorPlaceholder: '---',
)FormulaResultType values: number, dateTime, string
DSL:
.formula('total_cost',
title: 'Total Cost',
expression: 'course_fee * (1 + tax_rate / 100)')ReferenceField
Entity reference selection with multiple layout options and data providers.
ReferenceField(
name: 'instructor',
title: 'Instructor',
provider: StaticReferenceProviderConfiguration(options: [...]),
allowMultiple: false,
allowCreate: false,
maxSelections: null,
minSelections: null,
)Control type: FormControl<String> (single) or FormControl<List<String>> (multi)
Layouts:
| Layout | Description |
|---|---|
AutocompleteReferenceLayout | Type-ahead search (default) |
DropdownReferenceLayout | Standard dropdown |
ChipsReferenceLayout | Chip/tag selection |
RadioReferenceLayout | Radio button group |
CheckboxReferenceLayout | Checkbox group |
BarcodeScannerReferenceLayout | Barcode/QR scanner |
DSL:
.reference('instructor', title: 'Instructor')Summary Table
| Field Type | Schema Name | Control Type | Key Properties |
|---|---|---|---|
TextField | vyuh.formfield.text | String | isSecure, maxLines, maxLength, formatterMask |
NumberField | vyuh.formfield.number | num | allowDecimal |
SelectField | vyuh.formfield.select | String / List<String> | options, allowMultiple |
BooleanField | vyuh.formfield.boolean | bool | tristate |
DateTimeField | vyuh.formfield.datetime | DateTime | selectionType |
SliderField | vyuh.formfield.slider | double | min, max, divisions |
RangeSliderField | vyuh.formfield.rangeSlider | RangeValues | min, max, divisions |
PhoneNumberField | vyuh.formfield.phoneNumber | String | Filtered keyboard |
ImagePickerField | vyuh.formfield.imagePicker | List<XFile>? | maxImages |
FilePickerField | vyuh.formfield.filePicker | List<PlatformFile>? | allowedExtensions |
FormulaField | vyuh.formfield.formula | Computed | formula, resultType, numberFormat |
ReferenceField | vyuh.formfield.reference | String / List<String> | provider, allowMultiple, allowCreate |
Next Steps
- Validation -- Sync, async, soft, and context-aware validation
- Rules System -- Dynamic behavior with conditions and actions
- Field Configuration -- Detailed configuration guide per field type