change method

void change(
  1. String name,
  2. Object? value
)

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();
}