Add fields getter to FormState#180815
Conversation
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a public fields getter on FormState to expose the registered FormFieldState instances. The change is straightforward and includes comprehensive tests. My review focuses on improving the robustness of the new tests to prevent potential confusing failures.
# Conflicts: # packages/flutter/test/widgets/form_test.dart
justinmc
left a comment
There was a problem hiding this comment.
@Mairramer could you explain your concerns you posted in #110760 (comment) and if they apply here?
Five years ago I decided not to make this change (#67283 (comment)), but in the meantime I've become less strict about the Form API, as I hope to move to a replacement at some point.
Do you have any reason to make this change that my workaround I posted in that issue wouldn't solve?
The reason is that I’d like to avoid exposing the
In my case, the reason is that the company I work for has a design system, and to implement something similar to what I’m trying to integrate, I had to create some wrapper classes around TextFormField and TextEditingController. The solution works very well, but it could be significantly simplified if direct access to the fields were possible. For mobile apps, this is usually not an issue, since few screens have many text fields. The downside is more apparent in web apps, which typically involve larger and more complex forms. While I’m not certain if this is a strong argument, having direct access to the fields would be very useful and would significantly reduce boilerplate, as well as the number of wrappers currently required. |
|
@Mairramer Would you be able to share a code sample along the lines of what you're trying to achieve with this in your project? I'm inclined to land this but I want to be sure I understand the advantage to this approach in comparison with the current workaround I linked to. |
I have something similar to this: There is a caveat, though. As I mentioned, we have a design system and some abstractions on top of Flutter’s components to meet design specifications. Some are lightweight, while others are more involved. With direct access to the fields, the timing looks like this:
With traversal, it looks like this:
Even though both approaches are O(n), with Using fields makes it much simpler as well. |
|
I’m away from my PC right now, but if I’m not mistaken, I believe that even with your workaround, we still have access to the bucket, despite it being null. I’ll need to confirm this later. |
In your example, we also have access to the bucket, but it ends up being null anyway. In my example, this scenario applies more to web apps than to mobile apps, where we typically have an average of 2 to 3 However, we also have other components that are essentially thin wrappers around Flutter widgets. Since we encapsulate them within a |
|
|
||
| final List<FormFieldState<dynamic>> fields = formKey.currentState!.fields.toList(); | ||
|
|
||
| expect(fields.every((field) => field.isValid), isFalse); |
There was a problem hiding this comment.
Should this be fields.any(...) instead of fields.every(...)? With .every, this will pass if at least one it not valid. With .any, this would pass only if all are not valid.
There was a problem hiding this comment.
The use of every is correct, but the way I wrote it introduces a slight semantic inconsistency.
…ields-getter # Conflicts: # packages/flutter/test/widgets/form_test.dart
justinmc
left a comment
There was a problem hiding this comment.
LGTM 👍
@Mairramer I really appreciate your persistence in this PR and all your work answering my questions, including the Dartpad example. You've clearly explained the upsides and I can't think of any concrete downsides besides the maintenance burden, which is small. So let's land it.
|
Thanks, everyone! Even though I've moved on from Flutter, it’s great to see such a supportive community. 🫡 |
flutter/flutter@91b2d41...dad6f9d 2026-02-23 engine-flutter-autoroll@skia.org Roll Packages from 9da22bf to 12b43a1 (19 revisions) (flutter/flutter#182758) 2026-02-23 engine-flutter-autoroll@skia.org Roll Skia from 55fae1660572 to 9a5a3c92c336 (7 revisions) (flutter/flutter#182749) 2026-02-23 engine-flutter-autoroll@skia.org Roll Skia from 256e2b47b303 to 55fae1660572 (1 revision) (flutter/flutter#182741) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from 141ed451f007 to 256e2b47b303 (1 revision) (flutter/flutter#182732) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from e59de8a12e7e to 141ed451f007 (1 revision) (flutter/flutter#182729) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from f6ea7ef42d14 to e59de8a12e7e (1 revision) (flutter/flutter#182726) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from 34fa7b2373f3 to f6ea7ef42d14 (1 revision) (flutter/flutter#182721) 2026-02-21 engine-flutter-autoroll@skia.org Roll Skia from 3ca547c8b816 to 34fa7b2373f3 (2 revisions) (flutter/flutter#182711) 2026-02-21 engine-flutter-autoroll@skia.org Roll Skia from c91ad88e89f8 to 3ca547c8b816 (9 revisions) (flutter/flutter#182696) 2026-02-21 victorsanniay@gmail.com Shortcircuit if Tooltip message and richMessage are empty (flutter/flutter#182524) 2026-02-21 50643541+Mairramer@users.noreply.github.com Add fields getter to FormState (flutter/flutter#180815) 2026-02-20 1961493+harryterkelsen@users.noreply.github.com fix(web_ui): use static whitelist for image codec tests (flutter/flutter#182648) 2026-02-20 victorsanniay@gmail.com Add cupertino docimports for CupertinoPageTransitionsBuilder and fix typos (flutter/flutter#182685) 2026-02-20 katelovett@google.com Fix Chat invite link (flutter/flutter#182675) 2026-02-20 engine-flutter-autoroll@skia.org Roll Skia from ce5854495a3a to c91ad88e89f8 (58 revisions) (flutter/flutter#182678) 2026-02-20 30870216+gaaclarke@users.noreply.github.com Manual dart sdk flutter 174bcc79 25ff 4267 8e26 d0e902f18681 1771486449 (flutter/flutter#182624) 2026-02-20 97480502+b-luk@users.noreply.github.com Don't compile shaders to SkSL unless --sksl arg is present (flutter/flutter#182519) 2026-02-20 katelovett@google.com Correct PerformanceOverlay optionsMask checks and add tests (flutter/flutter#182309) 2026-02-20 jason-simmons@users.noreply.github.com [Impeller] libImpeller: Dispose thread local caches on each Vulkan frame (flutter/flutter#182402) 2026-02-20 31859944+LongCatIsLooong@users.noreply.github.com Update CHANGELOG for 3.41.2 stable hotfix (flutter/flutter#182647) 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 louisehsu@google.com,stuartmorgan@google.com 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
This PR exposes a public `FormState.fields` getter that returns all registered `FormFieldState` instances associated with a `Form`. Fixes flutter#110760 Fixes flutter#67283 Partially fixes flutter#107528 Partially fixes flutter#108110 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…r#11102) flutter/flutter@91b2d41...dad6f9d 2026-02-23 engine-flutter-autoroll@skia.org Roll Packages from 9da22bf to 12b43a1 (19 revisions) (flutter/flutter#182758) 2026-02-23 engine-flutter-autoroll@skia.org Roll Skia from 55fae1660572 to 9a5a3c92c336 (7 revisions) (flutter/flutter#182749) 2026-02-23 engine-flutter-autoroll@skia.org Roll Skia from 256e2b47b303 to 55fae1660572 (1 revision) (flutter/flutter#182741) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from 141ed451f007 to 256e2b47b303 (1 revision) (flutter/flutter#182732) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from e59de8a12e7e to 141ed451f007 (1 revision) (flutter/flutter#182729) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from f6ea7ef42d14 to e59de8a12e7e (1 revision) (flutter/flutter#182726) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from 34fa7b2373f3 to f6ea7ef42d14 (1 revision) (flutter/flutter#182721) 2026-02-21 engine-flutter-autoroll@skia.org Roll Skia from 3ca547c8b816 to 34fa7b2373f3 (2 revisions) (flutter/flutter#182711) 2026-02-21 engine-flutter-autoroll@skia.org Roll Skia from c91ad88e89f8 to 3ca547c8b816 (9 revisions) (flutter/flutter#182696) 2026-02-21 victorsanniay@gmail.com Shortcircuit if Tooltip message and richMessage are empty (flutter/flutter#182524) 2026-02-21 50643541+Mairramer@users.noreply.github.com Add fields getter to FormState (flutter/flutter#180815) 2026-02-20 1961493+harryterkelsen@users.noreply.github.com fix(web_ui): use static whitelist for image codec tests (flutter/flutter#182648) 2026-02-20 victorsanniay@gmail.com Add cupertino docimports for CupertinoPageTransitionsBuilder and fix typos (flutter/flutter#182685) 2026-02-20 katelovett@google.com Fix Chat invite link (flutter/flutter#182675) 2026-02-20 engine-flutter-autoroll@skia.org Roll Skia from ce5854495a3a to c91ad88e89f8 (58 revisions) (flutter/flutter#182678) 2026-02-20 30870216+gaaclarke@users.noreply.github.com Manual dart sdk flutter 174bcc79 25ff 4267 8e26 d0e902f18681 1771486449 (flutter/flutter#182624) 2026-02-20 97480502+b-luk@users.noreply.github.com Don't compile shaders to SkSL unless --sksl arg is present (flutter/flutter#182519) 2026-02-20 katelovett@google.com Correct PerformanceOverlay optionsMask checks and add tests (flutter/flutter#182309) 2026-02-20 jason-simmons@users.noreply.github.com [Impeller] libImpeller: Dispose thread local caches on each Vulkan frame (flutter/flutter#182402) 2026-02-20 31859944+LongCatIsLooong@users.noreply.github.com Update CHANGELOG for 3.41.2 stable hotfix (flutter/flutter#182647) 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 louisehsu@google.com,stuartmorgan@google.com 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
This PR exposes a public `FormState.fields` getter that returns all registered `FormFieldState` instances associated with a `Form`. Fixes flutter#110760 Fixes flutter#67283 Partially fixes flutter#107528 Partially fixes flutter#108110 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…r#11102) flutter/flutter@91b2d41...dad6f9d 2026-02-23 engine-flutter-autoroll@skia.org Roll Packages from 9da22bf to 12b43a1 (19 revisions) (flutter/flutter#182758) 2026-02-23 engine-flutter-autoroll@skia.org Roll Skia from 55fae1660572 to 9a5a3c92c336 (7 revisions) (flutter/flutter#182749) 2026-02-23 engine-flutter-autoroll@skia.org Roll Skia from 256e2b47b303 to 55fae1660572 (1 revision) (flutter/flutter#182741) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from 141ed451f007 to 256e2b47b303 (1 revision) (flutter/flutter#182732) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from e59de8a12e7e to 141ed451f007 (1 revision) (flutter/flutter#182729) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from f6ea7ef42d14 to e59de8a12e7e (1 revision) (flutter/flutter#182726) 2026-02-22 engine-flutter-autoroll@skia.org Roll Skia from 34fa7b2373f3 to f6ea7ef42d14 (1 revision) (flutter/flutter#182721) 2026-02-21 engine-flutter-autoroll@skia.org Roll Skia from 3ca547c8b816 to 34fa7b2373f3 (2 revisions) (flutter/flutter#182711) 2026-02-21 engine-flutter-autoroll@skia.org Roll Skia from c91ad88e89f8 to 3ca547c8b816 (9 revisions) (flutter/flutter#182696) 2026-02-21 victorsanniay@gmail.com Shortcircuit if Tooltip message and richMessage are empty (flutter/flutter#182524) 2026-02-21 50643541+Mairramer@users.noreply.github.com Add fields getter to FormState (flutter/flutter#180815) 2026-02-20 1961493+harryterkelsen@users.noreply.github.com fix(web_ui): use static whitelist for image codec tests (flutter/flutter#182648) 2026-02-20 victorsanniay@gmail.com Add cupertino docimports for CupertinoPageTransitionsBuilder and fix typos (flutter/flutter#182685) 2026-02-20 katelovett@google.com Fix Chat invite link (flutter/flutter#182675) 2026-02-20 engine-flutter-autoroll@skia.org Roll Skia from ce5854495a3a to c91ad88e89f8 (58 revisions) (flutter/flutter#182678) 2026-02-20 30870216+gaaclarke@users.noreply.github.com Manual dart sdk flutter 174bcc79 25ff 4267 8e26 d0e902f18681 1771486449 (flutter/flutter#182624) 2026-02-20 97480502+b-luk@users.noreply.github.com Don't compile shaders to SkSL unless --sksl arg is present (flutter/flutter#182519) 2026-02-20 katelovett@google.com Correct PerformanceOverlay optionsMask checks and add tests (flutter/flutter#182309) 2026-02-20 jason-simmons@users.noreply.github.com [Impeller] libImpeller: Dispose thread local caches on each Vulkan frame (flutter/flutter#182402) 2026-02-20 31859944+LongCatIsLooong@users.noreply.github.com Update CHANGELOG for 3.41.2 stable hotfix (flutter/flutter#182647) 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 louisehsu@google.com,stuartmorgan@google.com 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
This PR exposes a public
FormState.fieldsgetter that returns all registeredFormFieldStateinstances associated with aForm.Fixes #110760
Fixes #67283
Partially fixes #107528
Partially fixes #108110
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.