Skip to content

Conversation

@akashefrath
Copy link
Contributor

@akashefrath akashefrath commented Sep 17, 2025

This PR adds a new AutovalidateMode value:
onUserInteractionIfError.

This mode allows Form and FormField widgets to auto-validate only when a field already has an error and the user interacts with it again.

Why

  • Current modes (disabled, always, onUserInteraction, onUnfocus) do not cover the case where developers want validation only when correcting an error.
  • This improves UX by reducing unnecessary validation calls while still ensuring errors disappear as soon as the user fixes them.

How

  • Added onUserInteractionIfError to AutovalidateMode.
  • Updated Dartdoc with detailed description and example snippet.
  • Added new unit tests to validate behavior.
  • Verified no regressions in other modes (always, onUnfocus, onUserInteraction).

Example

TextFormField(
  autovalidateMode: AutovalidateMode.onUserInteractionIfError,
  validator: (value) => value!.isEmpty ? 'Required field' : null,
)

Related Issues

Fixes #<INSERT_RELATED_ISSUE_NUMBER_IF_ANY>


Tests

  • Added widget tests to confirm that:

    • No validation occurs until a field has an error.
    • Once an error exists, validation runs automatically on user interaction.
    • Resetting the form clears errors correctly.
  • Regression tests ensure that always, onUserInteraction, and onUnfocus modes still behave correctly.


Pre-launch / Reviewer Checklist


Breaking Change

  • Yes
  • No

Screenshots / Demo (if applicable)

(N/A — logic-only change)


Reviewer Notes

  • The new mode reduces unnecessary validation until the user corrects an error.
  • All tests confirm correct behavior and no regressions in existing modes.

@fluttergithubbot
Copy link
Contributor

An existing Git SHA, 7a01f9e517cba39fc283da4664da4abed47aad4f, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@github-actions github-actions bot added the framework flutter/packages/flutter repository. See also f: labels. label Sep 17, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new AutovalidateMode called onUserInteractionIfError. This mode triggers form field validation only when a user interacts with a field that already has an error. The implementation adds the new enum value, updates the logic in FormState and FormFieldState to handle this new mode, and includes comprehensive unit tests to verify the new behavior and prevent regressions. The changes are logical and well-implemented. My feedback includes a couple of minor style suggestions to improve code conciseness by leveraging Dart's type inference, in line with the Effective Dart style guide.

@justinmc justinmc self-requested a review October 14, 2025 23:09
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the real, long-term solution here is to give users more control over when errors are displayed. I have been meaning to work on this myself for years... But given that I haven't gotten around to it, I'm up for adding things like this for realistic use cases that aren't possible today. I think this one qualifies. Thanks for the PR.

@akashefrath
Copy link
Contributor Author

akashefrath commented Oct 22, 2025

I think that the real, long-term solution here is to give users more control over when errors are displayed. I have been meaning to work on this myself for years... But given that I haven't gotten around to it, I'm up for adding things like this for realistic use cases that aren't possible today. I think this one qualifies. Thanks for the PR.

Thanks so much for the thoughtful feedback! I completely agree — giving users more control over error display timing would definitely make validation more flexible and intuitive. I’m glad this use case aligns with that direction, and really appreciate your openness to the change.

And will fix the suggested changes,

@akashefrath akashefrath requested a review from justinmc October 22, 2025 10:20
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes! Two main things here: a use of a deprecated member, and some minor suggestions for improving the tests.

int _generation = 0;
bool _hasInteractedByUser = false;
final Set<FormFieldState<dynamic>> _fields = <FormFieldState<dynamic>>{};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unnecessary deletion? Or is this from dart format?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted, thanks! I only added back an empty line.

Copy link
Contributor

@Renzo-Olivares Renzo-Olivares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM w/ small nits. Thank you for the contribution!

@Piinks
Copy link
Contributor

Piinks commented Dec 9, 2025

It looks like this is ready to land, I am just going to rebase it first. Thanks for the contribution!

@Piinks
Copy link
Contributor

Piinks commented Dec 9, 2025

Oh! It looks like I cannot rebase, can you take a look @akashefrath?

@akashefrath
Copy link
Contributor Author

Oh! It looks like I cannot rebase, can you take a look @akashefrath?

Done. CI running .

@Piinks
Copy link
Contributor

Piinks commented Dec 10, 2025

Thank you!

@Piinks Piinks added the autosubmit Merge PR when tree becomes green via auto submit App label Dec 10, 2025
@auto-submit
Copy link
Contributor

auto-submit bot commented Dec 10, 2025

autosubmit label was removed for flutter/flutter/175515, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Dec 10, 2025
@akashefrath
Copy link
Contributor Author

@Piinks The autosubmit label was removed because the Google testing check failed earlier. I’ve now rebased the PR and re-tested, and currently only Tree Status is red; all other required checks are passing.

The remaining tree status failure is unrelated to this change. Could you please re-apply the autosubmit label to #175515?

Thank you

@Piinks Piinks added the autosubmit Merge PR when tree becomes green via auto submit App label Dec 10, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Dec 10, 2025
Merged via the queue into flutter:master with commit aaafeaf Dec 10, 2025
69 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Dec 10, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 10, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Dec 10, 2025
…10601)

Manual roll Flutter from 6a1f5b7f85a4 to e25d71b086d6 (30 revisions)

Manual roll requested by [email protected]

flutter/flutter@6a1f5b7...e25d71b

2025-12-10 [email protected] Ensure that the engine converts std::filesystem::path objects to UTF-8 strings on Windows (flutter/flutter#179528)
2025-12-10 [email protected] Fix the issue with pinned headers in nested SliverMainAxisGroup. (flutter/flutter#179132)
2025-12-10 [email protected] added onUserInteractionIfError for form (flutter/flutter#175515)
2025-12-10 [email protected] Fixed RenderFlex overflow in RouteObserver Example (flutter/flutter#170980)
2025-12-10 [email protected] Roll Dart SDK from 17749965ec57 to 077062c5e515 (3 revisions) (flutter/flutter#179691)
2025-12-10 [email protected] Manually roll characters (flutter/flutter#179447)
2025-12-10 [email protected] Roll Packages from 338ecd3 to 74a5a53 (4 revisions) (flutter/flutter#179693)
2025-12-10 [email protected] Marks Mac_ios draw_arcs_all_stroke_styles_perf_ios__timeline_summary to be unflaky (flutter/flutter#179669)
2025-12-10 [email protected] Check for a null cached image in SingleFrameCodec::getNextFrame (flutter/flutter#179483)
2025-12-10 [email protected] Roll Fuchsia Linux SDK from _pSztGZvEA3-Ry-GW... to u5vxWTRT0HlxOP5_r... (flutter/flutter#179652)
2025-12-10 [email protected] Implement flutter/accessibility channel (flutter/flutter#179484)
2025-12-10 [email protected] Roll Skia from 82fff05cc621 to e61cc6d073fd (4 revisions) (flutter/flutter#179646)
2025-12-10 [email protected] Make sure that a CupertinoDialogAction doesn't crash in 0x0 environment (flutter/flutter#178956)
2025-12-10 [email protected] Make SettingsChannel configuration queue not static (flutter/flutter#179636)
2025-12-10 [email protected] Make sure that a CupertinoListSection doesn't crash in 0x0 environment (flutter/flutter#179068)
2025-12-10 [email protected] Make sure that a CupertinoFormSection doesn't crash in 0x0 environment (flutter/flutter#179001)
2025-12-10 [email protected] Make sure that a CupertinoMagnifier doesn't crash in 0x0 environment (flutter/flutter#179206)
2025-12-10 [email protected] Make sure that a Tooltip doesn't crash in 0x0 environment (flutter/flutter#178461)
2025-12-10 [email protected] Make sure that a CupertinoSegmentedControl doesn't crash in 0x0 envir… (flutter/flutter#179544)
2025-12-10 [email protected] Make sure that a CupertinoSlider doesn't crash in 0x0 environment (flutter/flutter#179566)
2025-12-10 [email protected] Make sure that a CupertinoPageScaffold doesn't crash in 0x0 environment (flutter/flutter#179245)
2025-12-09 [email protected] Roll Skia from f9e32c28c5c5 to 82fff05cc621 (2 revisions) (flutter/flutter#179641)
2025-12-09 [email protected] Roll Dart SDK from 019cb923bf62 to 17749965ec57 (5 revisions) (flutter/flutter#179640)
2025-12-09 [email protected] Enhance documentation for `LocalHistoryEntry` class (flutter/flutter#179223)
2025-12-09 [email protected] WebParagrah: ellipsis (flutter/flutter#178748)
2025-12-09 [email protected] Update the doc on Google Testing to reflect the current state (flutter/flutter#177187)
2025-12-09 [email protected] [wimp] Initial Impeller on Web implementation. (flutter/flutter#175442)
2025-12-09 [email protected] Relax assertion for adding semantics locale (flutter/flutter#178140)
2025-12-09 [email protected] Fix Scrollbar drag behavior (flutter/flutter#179199)
2025-12-09 [email protected] Roll Skia from 502ee6f2a0d7 to f9e32c28c5c5 (6 revisions) (flutter/flutter#179632)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
...
Mairramer pushed a commit to Mairramer/flutter that referenced this pull request Dec 11, 2025
This PR adds a new `AutovalidateMode` value:  
`onUserInteractionIfError`.

This mode allows `Form` and `FormField` widgets to auto-validate **only
when a field already has an error and the user interacts with it
again**.

### Why
- Current modes (`disabled`, `always`, `onUserInteraction`, `onUnfocus`)
do not cover the case where developers want validation **only when
correcting an error**.
- This improves UX by reducing unnecessary validation calls while still
ensuring errors disappear as soon as the user fixes them.

### How
- Added `onUserInteractionIfError` to `AutovalidateMode`.  
- Updated Dartdoc with detailed description and example snippet.  
- Added new unit tests to validate behavior.  
- Verified no regressions in other modes (`always`, `onUnfocus`,
`onUserInteraction`).

### Example

```dart
TextFormField(
  autovalidateMode: AutovalidateMode.onUserInteractionIfError,
  validator: (value) => value!.isEmpty ? 'Required field' : null,
)
````

---

## Related Issues

Fixes #\<INSERT\_RELATED\_ISSUE\_NUMBER\_IF\_ANY>

---

## Tests

* Added widget tests to confirm that:

  * No validation occurs until a field has an error.
* Once an error exists, validation runs automatically on user
interaction.
  * Resetting the form clears errors correctly.
* Regression tests ensure that `always`, `onUserInteraction`, and
`onUnfocus` modes still behave correctly.

---

## Pre-launch / Reviewer Checklist

* [x] I have read the [[Contributor
Guide](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md)](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md)
* [x] I have read the \[Tree Hygiene] wiki page and followed its
guidance
* [x] I have read and followed the \[Flutter Style Guide]
* [x] I signed the \[CLA]
* [x] I added a new enum value with clear Dartdoc
(`onUserInteractionIfError`)
* [x] I added example code in the Dartdoc
* [x] I added new widget/unit tests for the new mode
* [x] All existing and new tests pass
* [x] I ran `flutter analyze` and fixed all issues
* [x] No breaking changes introduced (or marked accordingly)

---

## Breaking Change

* [x] Yes
* [x] No

---

## Screenshots / Demo (if applicable)

*(N/A — logic-only change)*

---

## Reviewer Notes

* The new mode reduces unnecessary validation until the user corrects an
error.
* All tests confirm correct behavior and no regressions in existing
modes.

---------

Co-authored-by: Loïc Sharma <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants