ResourceFormProvider class

Owns one form: its components, its values, its errors, and the /state round-trips a live field triggers.

Three rules govern /state, each of which has a real bug behind it:

  1. Values survive the swap. /state answers with components and no values, so _components is replaced and _values is never touched by a response. Rebuilding the values from the response resets the form and the user loses what they typed.
  2. Responses are sequenced. _stateId is bumped per dispatch and a response whose id is no longer current is dropped — the guard ResourceListProvider already carries, because P1 shipped this exact bug without it.
  3. /state's hidden is authoritative, /schema's is a first-paint hint, so every response overwrites the flag — and a field it reveals keeps whatever the user already typed into it, by rule 1.

Unlike ResourceListProvider this one does own a Timer: the debounce belongs to the field that is live, which only the provider knows about, and a screen debouncing every keystroke would defeat the point of live.

Inheritance

Constructors

ResourceFormProvider({required ResourceDataSource source, required ResourceSchema resource, required FilamentStrings strings, Object? recordId, RelationSubmitTarget? submitTarget, Duration stateDebounce = const Duration(milliseconds: 400)})

Properties

components List<SchemaComponent>
no setter
errorMessage String?
The initial load's failure, which is a different screen state entirely: there is no form to show yet.
no setter
fieldErrors Map<String, String>
no setter
formError String?
Unmappable 422 keys and save failures — the banner above the form.
no setter
hashCode int
The hash code for this object.
no setterinherited
hasListeners bool
Whether any listeners are currently registered.
no setterinherited
isUnauthenticated bool
True when load failed on a 401 — see FilamentTransportException.statusCode. Only the edit path's record() read can trip this; submit's 401 is not mapped here (see submit's doc).
no setter
recordId Object?
Null means create. Anything else is the record being edited.
final
resource ResourceSchema
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
savedRecordId Object?
The saved record's key as the server echoed it back, after the last successful submit; null before one, or when the response carried no record. PanelShell selects a just-created record with it (P23).
no setter
source ResourceDataSource
final
stateDebounce Duration
final
status LoadStatus
no setter
strings FilamentStrings
final
submitTarget RelationSubmitTarget?
Null — every form outside a relation manager — submits to resource's own endpoints exactly as before. Non-null redirects ONLY the write: rendering, seeding, /state and /options all stay on the child resource, because the child resource's form is what is on screen. This is the whole write-target override (P9); nothing else about the form knows it is editing a relation row.
final
submitting bool
no setter
values FormValues
no setter

Methods

addListener(VoidCallback listener) → void
Register a closure to be called when the object changes.
inherited
change(String name, Object? value) → void
Records one edit, and asks the server to re-evaluate the form only when the server itself marked that field live. Most forms make zero round-trips; a provider that called on every keystroke would be the performance bug live exists to avoid.
dispose() → void
Discards any resources used by the object.
override
load() Future<void>
Seeds the form. Create has nothing to fetch; edit reads the record, whose attributes carry the form's fields since Task 1 of P2.
mediaFor(String name) MediaSet?
The '<field>.__media' sibling for name, read off the record this form was seeded from. Null on create — there is no record — and null when the field carries no such sibling; see MediaSet.of.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
notifyListeners() → void
Call all the registered listeners.
inherited
optionsFor(String field) List<SelectOption>
The options last fetched for field, empty until one arrives.
removeListener(VoidCallback listener) → void
Remove a previously registered closure from the list of closures that are notified when the object changes.
inherited
searchOptions(String field, String query) Future<OptionsPage>
The options for a select whose list /schema refused to inline.
submit() Future<bool>
Validates client-side first, then writes. Returns true only when saved.
toString() String
A string representation of this object.
inherited
uploadFile(String name, {required List<int> bytes, required String filename}) Future<void>
Uploads bytes for a file field and applies the outcome.

Operators

operator ==(Object other) bool
The equality operator.
inherited