FormBuilder DSL
The FormBuilder provides a fluent API for constructing forms programmatically. It uses an auto-finalize pattern where starting a new field automatically commits the previous one.
Basic Usage
import 'package:vyuh_feature_forms/dsl/form_builder.dart';
final form = FormBuilder(title: 'My Form')
.text('name', title: 'Name')
.required()
.text('email', title: 'Email')
.email()
.build();FormBuilder Methods
Form-Level Configuration
FormBuilder(title: 'Title')
.description('Form description text')
.hSpacing(16.0) // Horizontal grid spacing
.vSpacing(16.0) // Vertical grid spacingField Creation Methods
Each method starts building a new field and auto-finalizes the previous one:
| Method | Returns | Creates |
|---|---|---|
.text(name, title:) | TextFieldBuilder | TextField |
.number(name, title:) | NumberFieldBuilder | NumberField |
.select(name, title:) | SelectFieldBuilder | SelectField |
.boolean(name, title:) | BooleanFieldBuilder | BooleanField |
.dateTime(name, title:) | DateTimeFieldBuilder | DateTimeField |
.slider(name, title:, min:, max:, divisions:) | SliderFieldBuilder | SliderField |
.phone(name, title:) | PhoneFieldBuilder | PhoneNumberField |
.file(name, title:) | FileFieldBuilder | FilePickerField |
.image(name, title:) | ImageFieldBuilder | ImagePickerField |
.formula(name, title:, expression:) | FormulaFieldBuilder | FormulaField |
.reference(name, title:) | ReferenceFieldBuilder | ReferenceField |
Section Method
.section('Section Title', (s) => s
.text('field1', title: 'Field 1')
.text('field2', title: 'Field 2'),
description: 'Optional description',
collapsible: true,
initiallyCollapsed: false,
rules: [When.fieldTrue('show_section').show()],
)The callback receives a fresh FormBuilder for the section's contents.
Build Method
.build(initialValues: {'name': 'Alice', 'email': 'alice@example.com'})Returns a fully constructed Form with wired FormGroup and all validations.
Shared Field Methods
Every FieldBuilder inherits these methods:
Validation
.required([String? message])
.email([String? message])
.pattern(String regex, {String? message})
.minLength(int min, {String? message})
.maxLength(int max, {String? message})
.identifier([String? message])
.asyncValidation(AsyncValidationConfiguration validation)Rules
.showWhen(When condition)
.hideWhen(When condition)
.enableWhen(When condition)
.disableWhen(When condition)Properties
.value(Object initialValue)
.placeholder(String text)
.help(String text)
.enabled(bool value) // Static enable/disable
.visible(bool value) // Static show/hide
.withLayout(LayoutConfiguration layout)Derivation
.derivedFrom(
{'source_field_1', 'source_field_2'},
transformer: (formValues) => computedValue,
initiallyDirty: false, // Set true in edit mode
)Type-Specific Methods
TextFieldBuilder
.text('field', title: 'Title')
.secure() // Password mode
.multiline(3) // Textarea with N lines
.charLimit(200) // Max character count
.mask('###-##-####') // Input formatter maskNumberFieldBuilder
.number('field', title: 'Title')
.decimal() // Allow decimals (default)
.integerOnly() // Integer only
.range(min: 1, max: 100)
.min(1)
.max(100)SelectFieldBuilder
.select('field', title: 'Title')
.option('value', title: 'Display')
.options({'val1': 'Display 1', 'val2': 'Display 2'})
.optionGroup('Group Title', [SelectOption(...)])
.multiple() // Multi-select modeBooleanFieldBuilder
.boolean('field', title: 'Title')
.tristate() // true/false/nullDateTimeFieldBuilder
.dateTime('field', title: 'Title')
.dateOnly() // Date picker only
.timeOnly() // Time picker only
.dateAndTime() // Both (default)SliderFieldBuilder
.slider('field', title: 'Title', min: 0, max: 10, divisions: 10)FormulaFieldBuilder
.formula('field', title: 'Title', expression: 'a + b * c')Complete Example: Course Enrollment
final form = FormBuilder(title: 'Course Enrollment')
// Student info (side-by-side)
.text('first_name', title: 'First Name')
.required('First name is required')
.text('last_name', title: 'Last Name')
.required('Last name is required')
.text('email', title: 'Email')
.required()
.email()
.phone('phone', title: 'Phone')
// Course selection
.select('course_id', title: 'Course')
.option('CS101', title: 'Intro to Computer Science')
.option('CS201', title: 'Data Structures')
.option('CS301', title: 'Algorithms')
.required('Please select a course')
// Enrollment details
.select('enrollment_type', title: 'Enrollment Type')
.option('open', title: 'Open (Free)')
.option('paid', title: 'Paid')
.required()
.dateTime('start_date', title: 'Start Date')
.dateOnly()
.required()
// Conditional payment section
.section('Payment', (s) => s
.select('payment_method', title: 'Payment Method')
.option('credit_card', title: 'Credit Card')
.option('bank_transfer', title: 'Bank Transfer')
.required('Payment method is required')
.text('card_number', title: 'Card Number')
.showWhen(When.fieldEquals('payment_method', 'credit_card'))
.required()
.pattern(r'^\d{16}$', message: 'Enter 16 digits'),
rules: [When.fieldEquals('enrollment_type', 'paid').show()],
)
// Preferences
.section('Preferences', (s) => s
.boolean('email_updates', title: 'Email Updates')
.help('Receive course announcements')
.select('schedule', title: 'Schedule')
.option('morning', title: 'Morning')
.option('afternoon', title: 'Afternoon')
.option('evening', title: 'Evening'),
collapsible: true,
)
.build();Auto-Finalize Pattern
The key design insight is that field builder methods are defined on both FormBuilder and FieldBuilder. When you call .text() on a TextFieldBuilder, it delegates to the parent FormBuilder, which:
- Finalizes the current field (calls
buildField()) - Adds it to the items list
- Creates and returns the new
TextFieldBuilder
This eliminates the need for explicit .done() or .end() calls between fields.
Rows and Explicit Layout
The DSL builds a sequential Form with optional sections. Field builders do not expose row spans. For explicit side-by-side layouts, create a FormRowBlock in the runtime model or use Row blocks in the visual editor; both serialize row items as { field, span } while each field still registers as a normal control in the form's single FormGroup.
Next Steps
- Building Forms -- Step-by-step form construction
- Dynamic Behavior -- Rules and conditional logic
- Form Model -- The underlying data structures