submit method

Future<bool> submit()

Validates client-side first, then writes. Returns true only when saved.

A 401 here is not mapped to isUnauthenticated: a transport failure on write already lands in WriteFailed and shows through formError, same as any other save failure, and a token that expired mid-edit is a save the user can retry from the same screen once signed back in — it is not the "there is no form to show" case isUnauthenticated exists for. Same scope choice Task 5 made for loadMore().

Implementation

Future<bool> submit() async {
  if (_submitting) return false;

  _formError = null;
  _fieldErrors = Map.unmodifiable(validate(_components, _values, strings));

  // A hint may only delay a submission by a round-trip; it never reaches the
  // server, so nothing here can forbid what the server would accept.
  if (_fieldErrors.isNotEmpty) {
    notifyListeners();
    return false;
  }

  _submitting = true;
  notifyListeners();

  final payload = _values.payloadFor(_components);
  WriteResult result;
  try {
    final target = submitTarget;
    // One branch, two URL families: the relation target changes WHERE the
    // payload goes, never what it is — validation, the 422 mapping and the
    // banner below are shared verbatim, because the server keys a relation
    // write's 422 by the same child-form field names this screen renders.
    result = target == null
        ? recordId == null
              ? await _source.create(resource.key, payload)
              : await _source.update(resource.key, recordId!, payload)
        : recordId == null
        ? await _source.createRelation(
            target.resourceKey,
            target.recordId,
            target.relation,
            payload,
          )
        : await _source.updateRelation(
            target.resourceKey,
            target.recordId,
            target.relation,
            recordId!,
            payload,
          );
  } catch (e) {
    // create/update return their 4xx as data; only a transport failure
    // throws, and its message is already fit for the user.
    result = WriteFailed(messageOf(e));
  }

  _submitting = false;

  switch (result) {
    case WriteSuccess():
      _notify();
      return true;
    case WriteInvalid(:final errors):
      _applyServerErrors(errors);
    case WriteDenied(:final message) ||
        WriteGone(:final message) ||
        WriteFailed(:final message):
      _formError = message.isEmpty ? strings.saveFailed : message;
  }

  _notify();
  return false;
}