change method
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.
Implementation
void change(String name, Object? value) {
final previous = _values[name];
_values = _values.set(name, value);
// The server's message for this field described the value that was just
// replaced. Leaving it up would blame the user for the edit they made.
if (_fieldErrors.isNotEmpty) {
final next = Map<String, String>.of(_fieldErrors)..remove(name);
// A repeater's own onChanged always replaces its whole row list, so a
// row-scoped error ('<name>.<row>.<child>', the same shape
// `client_validator.dart` and a server 422 both use) is never named by
// `name` alone and would otherwise survive however many times the row
// it names gets fixed — this is new with repeater support; no other
// field produces a dotted error key that `remove(name)` above can't
// reach. `RepeaterFieldWidget` gives every *untouched* row the same
// Map instance across an edit (its own row-independence guarantee —
// see its class doc), so identity alone says which row actually
// changed, and only that row's stale errors clear — a still-invalid
// sibling row keeps its error.
if (previous is List && value is List) {
for (var i = 0; i < value.length; i++) {
if (i < previous.length && identical(previous[i], value[i])) {
continue;
}
next.removeWhere((key, _) => key.startsWith('$name.$i.'));
}
}
_fieldErrors = Map.unmodifiable(next);
}
if (_isLive(name)) _scheduleState(name);
notifyListeners();
}