submit<X> method
FutureOr<FormSubmitResult<X> >
submit<X>(
- BuildContext context, {
- FutureOr<
X?> submit()?, - bool? skipIfUnmodified,
override
Submits this form, including subforms, and returns the result
Implementation
@override
FutureOr<FormSubmitResult<X>> submit<X>(BuildContext context,
{FutureOr<X?> submit()?, bool? skipIfUnmodified}) async {
skipIfUnmodified ??= false;
final start = DateTime.now();
startSubmission();
var result = FormSubmitResultBuilder<X>.start(this);
for (final entry in readyChecks.entries) {
log.info("Awaiting ready check: ${entry.key}");
if (entry.value.isActive) {
await entry.value.future;
log.info("Finished ready check: ${entry.key}");
} else {
log.info("Found ready check, but it was not active: ${entry.key}");
}
}
final hasChanges = skipIfUnmodified != true || isModified;
/// first, validate all the way down the chain:
final validationErrors = await validate(skipIfUnmodified: skipIfUnmodified);
if (validationErrors.isNotEmpty && hasChanges) {
result
..validationErrors = validationErrors
..resultType = ResultType.error
..message = "Validation error";
return result.end();
}
final copy = [..._subforms];
for (final subform in copy) {
try {
log.info(
"Submitting subform ${subform!.name}: modified=${subform.isModified} ${skipIfUnmodified != true ? '(saving anyway)' : ''}");
///
/// Submitting each subform
///
final subformResult =
await subform.submit(context, skipIfUnmodified: skipIfUnmodified);
log.info("Done with ${subform.name} subform ${subform.name}");
result.subforms[subform.name] = subformResult;
if (subformResult.isError) {
log.warning(
"Early termination from subform ${subform.name}: ${subformResult.message}");
result
..resultType = ResultType.error
..message =
"Subform error ${subform.name}: ${subformResult.message}";
return result.end();
}
} catch (e) {
result.subforms[subform!.name] = FormSubmitResult.error(this, e);
result
..resultType = ResultType.error
..message = "$e";
return result.end();
}
}
try {
// Run onSubmits
final hooks = [..._submitHooks.entries];
if (skipIfUnmodified != true || isModified) {
for (final hook in hooks) {
log.info("Executing hook: ${hook.key}");
final hookResult = await hook.value(this, result);
result.submitHooks[hook.key] = hookResult;
if (!hookResult.isSuccessful) {
result
..resultType = ResultType.error
..message =
"Failed submit hook ${hook.key}: ${hookResult.message}";
return result.end();
}
log.info("Hook: ${hook.key}: $hookResult");
}
X? submitResult = (await submit?.call());
result
..value = submitResult
..resultType = ResultType.success;
} else {
result..resultType = ResultType.skipped;
}
return result.end();
} catch (e, stack) {
if (e is BadRequestException) {
result.validationErrors = e.validationErrors.groupBy((e) => e.path);
this.updateErrors(e.validationErrors, source: AttributeSource.model);
result.message = "Validation Errors";
} else {
result.message = "Error submitting form";
log.info(e);
log.info(stack);
SunnyHud.error(context, "Error submitting form");
}
result.resultType = ResultType.error;
return result.end();
} finally {
endSubmission();
log.info(
"Form submitted in ${DateTime.now().difference(start).inMilliseconds}");
}
}