FormSchema class abstract
A base class for strongly-typed, aggregate form schemas.
What you must implement
- namedInputs — maps serialization keys to input instances.
copyWith— field-level mutation (manual, Freezed, or build_runner).- touchAll — marks every input touched via your
copyWith. - reset — resets every input to its initial value and increments
formKey via your
copyWith.
What you may override
- nestedSchemas — embed sub-schemas for sections (address, billing…).
- schemaValidators — cross-field validation rules.
- populateFrom — pre-fill from a data map for edit flows.
Minimal example
class LoginSchema extends FormSchema {
final EmailInput email;
final PasswordInput password;
const LoginSchema({
this.email = const EmailInput.untouched(),
this.password = const PasswordInput.untouched(),
super.formKey,
});
@override
Map<String, FormInput> get namedInputs =>
{'email': email, 'password': password};
LoginSchema copyWith({
EmailInput? email,
PasswordInput? password,
int? formKey,
}) => LoginSchema(
email: email ?? this.email,
password: password ?? this.password,
formKey: formKey ?? this.formKey,
);
@override
LoginSchema touchAll() => copyWith(
email: email.markTouched(),
password: password.markTouched(),
// formKey unchanged — touchAll is not a reset
);
@override
LoginSchema reset() => LoginSchema(
// nextFormKey increments the counter → triggers widget recreation.
formKey: nextFormKey,
);
}
Using formKey to reset visible text without controllers
TextField(onChanged: ...) owns its text internally and ignores
programmatic value changes after the first build. The only way to reset
the visible text without a TextEditingController is to change the
widget's key, which causes Flutter to destroy and recreate it.
Pass formKey as a ValueKey prefix on every text field:
// StatelessWidget — no TextEditingController, no StatefulWidget needed.
TextField(
key: ValueKey('${state.schema.formKey}_email'),
onChanged: cubit.emailChanged,
decoration: InputDecoration(
errorText: state.schema.email.displayError(state.status)?.message(context),
),
)
When reset is called the cubit emits a schema with an incremented
formKey. Flutter sees a new key, destroys the old TextField, and
creates a fresh one — visible text cleared, no controllers required.
Constructors
- FormSchema({int formKey = 0})
-
const
Properties
-
changedValues
→ Map<
String, dynamic> -
no setter
- errors → List
-
no setter
- firstError → dynamic
-
no setter
- formKey → int
-
A monotonically increasing integer, incremented each time reset is
called.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
-
inputs
→ List<
FormInput> -
no setter
-
invalidInputs
→ List<
FormInput> -
no setter
- isModified → bool
-
no setter
- isNotValid → bool
-
no setter
- isSchemaValid → bool
-
no setter
- isTouched → bool
-
no setter
- isUntouched → bool
-
no setter
- isValid → bool
-
no setter
-
namedErrors
→ Map<
String, dynamic> -
no setter
-
namedInputs
→ Map<
String, FormInput> -
Maps serialization keys to their respective input instances.
no setter
-
nestedSchemas
→ Map<
String, FormSchema> -
Sub-schemas embedded in this schema (address, billing, etc.).
no setter
- nextFormKey → int
-
Returns
formKey + 1.no setter - runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- schemaErrors → List
-
no setter
-
schemaValidators
→ List<
SchemaValidator> -
Cross-field validation rules.
no setter
-
values
→ Map<
String, dynamic> -
no setter
Methods
-
firstErrorOf<
E> () → E? -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
populateFrom(
Map< String, dynamic> data) → FormSchema -
Pre-fills all inputs from
dataand marks them touched. -
reset(
) → FormSchema - Returns a new schema with every input reset to its FormInput.initialValue and InputStatus.untouched, and with formKey incremented.
-
toString(
) → String -
A string representation of this object.
inherited
-
touchAll(
) → FormSchema - Returns a new schema with every input marked InputStatus.touched.
-
validate(
) → (FormSchema, bool) - Touches all inputs then checks validity — the canonical submit guard.
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited