-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Fix DropdownMenu does not rematch initialSelection when entries have changed #155757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix DropdownMenu does not rematch initialSelection when entries have changed #155757
Conversation
nate-thegrate
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks phenomenal—thanks for the fix and the thorough testing!
A bunch of random suggestions, most of which are due to how List<DropdownMenuEntry<T>> has a tendency to make lines super long :)
| // whose value matches the initial selection. | ||
| // Empty the text field when no entry matches the initial selection. | ||
| void matchInitialSelection() { | ||
| final int index = filteredEntries.indexWhere((DropdownMenuEntry<T> entry) => entry.value == widget.initialSelection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| final int index = filteredEntries.indexWhere((DropdownMenuEntry<T> entry) => entry.value == widget.initialSelection); | |
| final int index = filteredEntries.indexWhere( | |
| (DropdownMenuEntry<T> entry) => entry.value == widget.initialSelection, | |
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not fond of this formatting. It reduces the long lines but the style guide explictly mention that going above 80 is preferrable when the result is more readable.
Nonetheless I applied it:
- because readability is somewhat subjective.
- I used the same formatting on a very recent PR.
- maybe we will get autoformat in the coming months (and subjectivity will be gone 😄 ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a reviewer but I came across this PR. I'm also not a fan of the indented closure formatting. How would you both feel about something like:
TextEditingValue get _initialTextEditingValue {
for (final entry in filteredEntries) {
if (entry.value == widget.initialSelection) {
return TextEditingValue(
text: entry.label,
selection: TextSelection.collapsed(offset: entry.label.length),
);
}
}
return TextEditingValue.empty;
}where _localTextEditingController?.value = _initialTextEditingValue is set in didUpdateWidget. It could also be a function rather than a getter.
I think the current function being a void 'match'-er rather than a setter made the purpose ambigious without viewing the implementation (or the comments).
That said, feel free to ignore this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @davidhicks980! Really like this approach, avoiding the 'macth'-er function makes the logic more understandable.
4b6c027 to
211e059
Compare
nate-thegrate
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Fantastic improvements all-around, thank you!
|
I will probably wait for #155252 to land (I will solve the conflicts on my side). |
c65ab4e to
4571c55
Compare
4571c55 to
18444c8
Compare
Manual roll Flutter from 0975e61 to ec2e12b (54 revisions) Manual roll requested by [email protected] flutter/flutter@0975e61...ec2e12b 2024-10-03 [email protected] Roll Flutter Engine from bd44b58e3204 to 247bc68c578e (7 revisions) (flutter/flutter#156144) 2024-10-03 [email protected] Roll Flutter Engine from 70232fa124d0 to bd44b58e3204 (1 revision) (flutter/flutter#156124) 2024-10-03 [email protected] Roll Flutter Engine from 33ac1b30ab0a to 70232fa124d0 (2 revisions) (flutter/flutter#156122) 2024-10-02 [email protected] Update `ThemeData.dialogTheme` type to accept `DialogThemeData` (flutter/flutter#155129) 2024-10-02 [email protected] Roll Flutter Engine from 751ab9b3c5eb to 33ac1b30ab0a (4 revisions) (flutter/flutter#156118) 2024-10-02 [email protected] Add back main() methods to benchmark benches. (flutter/flutter#156083) 2024-10-02 [email protected] Roll pub packages (flutter/flutter#156117) 2024-10-02 [email protected] Add `mouseCursor` property to `CupertinoCheckbox` (flutter/flutter#151788) 2024-10-02 [email protected] Roll Flutter Engine from 3bdc1c0a30b6 to 751ab9b3c5eb (3 revisions) (flutter/flutter#156115) 2024-10-02 [email protected] Roll pub packages (flutter/flutter#156114) 2024-10-02 [email protected] [ Cocoon ] Wait for task results to be received by the task runner before shutting down the task process (flutter/flutter#156002) 2024-10-02 [email protected] Allow mixing route transitions in one app. (flutter/flutter#150031) 2024-10-02 [email protected] Roll Flutter Engine from f20681241753 to 3bdc1c0a30b6 (5 revisions) (flutter/flutter#156107) 2024-10-02 [email protected] Update Upgrading-Engine's-Android-API-version.md to reflect code move (flutter/flutter#156108) 2024-10-02 [email protected] Roll Packages from ebcc4f0 to 7c97c88 (5 revisions) (flutter/flutter#156106) 2024-10-02 [email protected] Roll pub packages (flutter/flutter#156105) 2024-10-02 [email protected] fix wrong test in "fixing `DropdownMenu` keyboard navigation" (flutter/flutter#156084) 2024-10-02 [email protected] fix ReorderableList not passing in item extent builder (flutter/flutter#155994) 2024-10-02 98614782+auto-submit[bot]@users.noreply.github.com Reverts "integration_test: migrate to build.gradle.kts (#154125)" (flutter/flutter#156087) 2024-10-02 [email protected] Add deprecation warning for "flutter create --ios-language" (flutter/flutter#155867) 2024-10-02 [email protected] update flutter create generated projects to use package:flutter_lints 5.0.0 (flutter/flutter#156011) 2024-10-02 [email protected] Roll Flutter Engine from d48c35d16814 to f20681241753 (1 revision) (flutter/flutter#156080) 2024-10-02 [email protected] [Docs] `CupertinoListTile` API Example (flutter/flutter#154548) 2024-10-02 [email protected] integration_test: migrate to build.gradle.kts (flutter/flutter#154125) 2024-10-02 [email protected] Marks Windows_mokey native_assets_android to be flaky (flutter/flutter#156064) 2024-10-02 [email protected] Fix DropdownMenu does not rematch initialSelection when entries have changed (flutter/flutter#155757) 2024-10-02 [email protected] Roll Flutter Engine from 9b224bd2f895 to d48c35d16814 (1 revision) (flutter/flutter#156074) 2024-10-02 [email protected] Roll Flutter Engine from 8774940b9ddc to 9b224bd2f895 (1 revision) (flutter/flutter#156065) 2024-10-02 [email protected] Roll Flutter Engine from 21ad04948457 to 8774940b9ddc (1 revision) (flutter/flutter#156055) 2024-10-02 [email protected] Roll Flutter Engine from 767bdc38cf51 to 21ad04948457 (1 revision) (flutter/flutter#156049) 2024-10-02 [email protected] Roll Flutter Engine from 055969512dc5 to 767bdc38cf51 (1 revision) (flutter/flutter#156043) 2024-10-02 [email protected] Roll Flutter Engine from e0f049d69240 to 055969512dc5 (2 revisions) (flutter/flutter#156042) 2024-10-02 [email protected] fix `DropdownMenu` keyboard navigation when entries are filtered empty (flutter/flutter#155252) 2024-10-02 [email protected] Roll Flutter Engine from a5bc2e2708c7 to e0f049d69240 (1 revision) (flutter/flutter#156039) 2024-10-02 [email protected] mark {Linux,Windows} tool_integration_tests_* non-bringup (flutter/flutter#155773) 2024-10-02 [email protected] Roll Flutter Engine from a7abf7a8163e to a5bc2e2708c7 (2 revisions) (flutter/flutter#156038) 2024-10-02 [email protected] Roll Flutter Engine from df1982dd4482 to a7abf7a8163e (1 revision) (flutter/flutter#156032) 2024-10-02 [email protected] Add `enableSplash` parameter to `CarouselView` (flutter/flutter#155214) 2024-10-02 [email protected] Roll pub packages (flutter/flutter#156030) 2024-10-01 [email protected] Roll Flutter Engine from ab48d6d8c167 to df1982dd4482 (1 revision) (flutter/flutter#156029) 2024-10-01 [email protected] Marks Mac_arm64_ios hot_mode_dev_cycle_ios__benchmark to be unflaky (flutter/flutter#147289) 2024-10-01 [email protected] Add WidgetStateMouseCursor example and tests for it. (flutter/flutter#155552) 2024-10-01 49699333+dependabot[bot]@users.noreply.github.com Bump codecov/codecov-action from 4.5.0 to 4.6.0 (flutter/flutter#156024) 2024-10-01 [email protected] Roll Flutter Engine from e7b3ce717006 to ab48d6d8c167 (1 revision) (flutter/flutter#156023) ...
## Description This PR reverts `DropdownMenu` changes from #155757. Automatically rematching the `initialSelection` breaks some use cases. It is more flexible to let users manipulate the text field content using the TextEditingController. ## Related Issue Fixes [Dropdown Menu Creates Infinite Build Loop](#160196) Fixes [Can no longer initialize non selectable value in DropdownMenu as of flutter version 3.27.1](#160555) ## Tests Removes 2 regression tests from #155757. Keeps 2 tests from the original PR (missing test for the initialSelection behavior). Adds 1 tests to avoid regressing this revert.
…n when entries have changed" (#161177) This pull request reverts the changes in #155757. The auto-formatter created conflicts in the master branch, so the revert was performed manually in #160643. For this cherry-pick PR, I was able to run `git revert 21381d8` without any problems. <br> ### Issue Links bug reports: #160196, #160555 cherry-pick request: #161176 ### Target stable ### Changelog Description Passing a list literal to a `DropdownMenu` causes the widget to reset to the `initialSelection` after each build. ### Impacted Users This affects anyone using the [DropdownMenu](https://api.flutter.dev/flutter/material/DropdownMenu-class.html) widget. ### Impact Description The impact usually consists of the text value being inconveniently reset each time the widget is rebuilt. (In some cases it can be a fatal crash: the code sample from #160196 shows how this change can lead to an infinite build loop.) ### Workaround This regression can be mitigated by caching & modifying a single list instance, rather than using a list literal for the `DropdownMenu` constructor. ### Risk low ### Test Coverage yes ### Validation Steps #160643 added a regression test for this revert. The fix can also be verified by running the code sample from #160196 and verifying that there is no infinite build loop.
## Description The current behavior of Flutter regarding `DropdownMenu` text field is very basic: `DropdownMenu` updates the text field once a selection has been made with its coordinating `label`, and nothing more. If the selection's `label` changes, the text field will still show the old value, although the menu buttons have been updated. This not only results in the need to write a lot of boilerplate code to match the label to the current selection, but it's also counterintuitive. The `DropdownMenu` should handle rematching by itself. Issue #155660, touched on this, and a solution was introduced in #155757. It was later reverted due to it restricting some use cases. That issue & solution, however, only address `initialSelection`. If another selection was made and its corresponding `label` was changed, the text field would still show the old value, bringing us back to square one. This PR should not conflict with any previous behavior of `DropdownMenu`: any new value provided by `initialSelection` or via controller would not be overwritten by rematching. However, entries with the same value will be mapped to a single label (the first matched entry's label). ## Related Issues - Fixes #155660. ## Tests Added 3 tests. ## 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]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
## Description The current behavior of Flutter regarding `DropdownMenu` text field is very basic: `DropdownMenu` updates the text field once a selection has been made with its coordinating `label`, and nothing more. If the selection's `label` changes, the text field will still show the old value, although the menu buttons have been updated. This not only results in the need to write a lot of boilerplate code to match the label to the current selection, but it's also counterintuitive. The `DropdownMenu` should handle rematching by itself. Issue flutter#155660, touched on this, and a solution was introduced in flutter#155757. It was later reverted due to it restricting some use cases. That issue & solution, however, only address `initialSelection`. If another selection was made and its corresponding `label` was changed, the text field would still show the old value, bringing us back to square one. This PR should not conflict with any previous behavior of `DropdownMenu`: any new value provided by `initialSelection` or via controller would not be overwritten by rematching. However, entries with the same value will be mapped to a single label (the first matched entry's label). ## Related Issues - Fixes flutter#155660. ## Tests Added 3 tests. ## 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]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
Description
This PR makes DropdownMenu rematching the initialSelection when the entries are updated.
If the new entries contains one entry whose value matches
initialSelectionthis entry's label is used to initialize the inner text field, if no entries matchesinitialSelectionthe text field is emptied.Related Issue
Fixes DropdownMenu.didUpdateWidget should re-match initialSelection when dropdownMenuEntries have changed.
Tests
Adds 3 tests.