Rules System
The rules system provides declarative dynamic behavior for form fields. Each rule is a pair: a condition that evaluates form state, and an action that modifies a field when the condition is met.
FormFieldRule
class FormFieldRule implements SchemaItem {
final RuleCondition condition;
final RuleAction action;
}Rules are evaluated reactively. When any field that a condition depends on changes, the rule re-evaluates and the action is applied.
Conditions
Conditions evaluate form field values and return a boolean. All conditions implement RuleCondition:
abstract class RuleCondition implements SchemaItem {
Set<String> getDependencies();
bool evaluate(Map<String, dynamic> formValues);
}6 Condition Types
BooleanCondition
Checks if a boolean field is true or false.
BooleanCondition(
targetField: 'is_international',
operator: BooleanOperator.isTrue, // or isFalse
)StringCondition
String comparison with 9 operators.
StringCondition(
targetField: 'enrollment_type',
operator: StringOperator.equals,
value: 'paid',
caseSensitive: false, // default
)StringOperator values: equals, notEquals, contains, notContains, startsWith, endsWith, matches (regex), isEmpty, isNotEmpty
NumericCondition
Numeric comparison with 6 operators.
NumericCondition(
targetField: 'team_size',
operator: NumericOperator.greaterThan,
value: 5,
maxValue: null, // used with 'between'
)NumericOperator values: equal, greaterThan, lessThan, greaterEqual, lessEqual, between
DateCondition
Date comparison with 4 operators.
DateCondition(
targetField: 'start_date',
operator: DateOperator.after,
date: DateTime.now(),
endDate: null, // used with 'between'
)DateOperator values: before, after, on, between
EmptyCondition
Checks if a field value is null, empty string, empty list, or empty map.
EmptyCondition(targetField: 'notes')CompoundCondition
Combines multiple conditions with AND/OR logic.
CompoundCondition(
operator: ConditionOperator.and, // or ConditionOperator.or
conditions: [
StringCondition(targetField: 'type', operator: StringOperator.equals, value: 'paid'),
BooleanCondition(targetField: 'is_international', operator: BooleanOperator.isTrue),
],
)Actions
Actions modify field behavior when their condition evaluates. All actions implement RuleAction:
abstract class RuleAction implements SchemaItem {
void apply(FormField targetField, bool conditionMet, BuildContext context);
}6 Action Types
VisibilityAction
Shows or hides a field based on the condition.
VisibilityAction(showWhenTrue: true) // Show when condition met, hide otherwise
VisibilityAction(showWhenTrue: false) // Hide when condition met, show otherwiseEnabledAction
Enables or disables a field based on the condition.
EnabledAction(enableWhenTrue: true) // Enable when condition met
EnabledAction(enableWhenTrue: false) // Disable when condition metSetValueAction
Sets a field's value when the condition is met.
SetValueAction(value: 'default_course')FocusAction
Moves focus to a specific field when the condition is met.
FocusAction(
targetFieldName: 'payment_method',
focusWhenTrue: true,
)ValidationAction
Adds or removes a validation rule dynamically based on the condition.
ValidationAction(
validationType: 'required', // 'required', 'email', 'pattern'
errorMessage: 'Payment method is required for paid enrollments',
addWhenTrue: true, // Add validation when condition met
)Uses the field's DynamicValidator to activate/deactivate validations at runtime.
CompoundAction
Applies multiple actions together.
CompoundAction(actions: [
VisibilityAction(showWhenTrue: true),
EnabledAction(enableWhenTrue: true),
])LMS Examples
Show Payment Fields for Paid Enrollment
// Payment method: visible only when enrollment type is 'paid'
TextField(
name: 'payment_method',
title: 'Payment Method',
rules: [
FormFieldRule(
condition: StringCondition(
targetField: 'enrollment_type',
operator: StringOperator.equals,
value: 'paid',
),
action: VisibilityAction(showWhenTrue: true),
),
],
)Make Field Required When Visible
// Payment method: required only when enrollment type is 'paid'
TextField(
name: 'payment_method',
title: 'Payment Method',
rules: [
// Show when paid
FormFieldRule(
condition: StringCondition(
targetField: 'enrollment_type',
operator: StringOperator.equals,
value: 'paid',
),
action: VisibilityAction(showWhenTrue: true),
),
// Also make required when paid
FormFieldRule(
condition: StringCondition(
targetField: 'enrollment_type',
operator: StringOperator.equals,
value: 'paid',
),
action: ValidationAction(
validationType: 'required',
errorMessage: 'Payment method is required',
addWhenTrue: true,
),
),
],
)Compound Condition: International Paid Students
FormFieldRule(
condition: CompoundCondition(
operator: ConditionOperator.and,
conditions: [
StringCondition(
targetField: 'enrollment_type',
operator: StringOperator.equals,
value: 'paid',
),
BooleanCondition(
targetField: 'is_international',
operator: BooleanOperator.isTrue,
),
],
),
action: VisibilityAction(showWhenTrue: true),
)When DSL
The When class provides a fluent DSL for creating rules:
// String conditions
When.fieldEquals('type', 'paid')
When.fieldNotEquals('type', 'free')
When.fieldContains('name', 'admin')
When.fieldEmpty('notes')
When.fieldNotEmpty('email')
// Boolean conditions
When.fieldTrue('is_active')
When.fieldFalse('is_draft')
// Compound conditions
When.allOf([When.fieldEquals('type', 'paid'), When.fieldTrue('international')])
When.anyOf([When.fieldEquals('type', 'paid'), When.fieldEquals('type', 'sponsored')])
// Actions
When.fieldEquals('type', 'paid').show() // VisibilityAction(showWhenTrue: true)
When.fieldEquals('type', 'paid').hide() // VisibilityAction(showWhenTrue: false)
When.fieldEquals('type', 'paid').enable() // EnabledAction(enableWhenTrue: true)
When.fieldEquals('type', 'paid').disable() // EnabledAction(enableWhenTrue: false)Used in the FormBuilder DSL:
.text('payment_method', title: 'Payment Method')
.showWhen(When.fieldEquals('enrollment_type', 'paid'))
.required()Section Rules
FormSection also supports rules for section-level visibility:
FormBuilder(title: 'Application')
.section('International Details', (s) => s
.text('passport', title: 'Passport Number')
.text('visa_type', title: 'Visa Type'),
rules: [When.fieldTrue('is_international').show()],
)
.build();Next Steps
- FormBuilder DSL -- Complete DSL reference
- Dynamic Behavior -- Step-by-step guide to rules
- Validation -- Validation pipeline details