From be627165df5b6f2d226d476d609f7853528474d4 Mon Sep 17 00:00:00 2001 From: Memet <54338732+Memet18@users.noreply.github.com> Date: Mon, 24 Mar 2025 08:07:51 +0100 Subject: [PATCH] feat: Added forceErrorText in DropdownButtonFormField #165188 (#165189) Feat: Added forceErrorText in DropdownButtonFormField #165188 ## 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. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [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 --------- Co-authored-by: Bruno Leroux --- .../flutter/lib/src/material/dropdown.dart | 1 + .../material/dropdown_form_field_test.dart | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index a75e7c3dcd..f7f8a0c113 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -1731,6 +1731,7 @@ class DropdownButtonFormField extends FormField { super.onSaved, super.validator, super.errorBuilder, + super.forceErrorText, AutovalidateMode? autovalidateMode, double? menuMaxHeight, bool? enableFeedback, diff --git a/packages/flutter/test/material/dropdown_form_field_test.dart b/packages/flutter/test/material/dropdown_form_field_test.dart index 4282aaf747..1aee955310 100644 --- a/packages/flutter/test/material/dropdown_form_field_test.dart +++ b/packages/flutter/test/material/dropdown_form_field_test.dart @@ -1294,4 +1294,92 @@ void main() { await tester.pumpWidget(buildFrame(alignedDropdown: true, textDirection: TextDirection.rtl)); expect(tester.getRect(findSelectedValue), contentRectForUnalignedDropdown); }); + + testWidgets('isValid returns false when forceErrorText is set and changes error display', ( + WidgetTester tester, + ) async { + final GlobalKey> fieldKey1 = GlobalKey>(); + final GlobalKey> fieldKey2 = GlobalKey>(); + const String forceErrorText = 'Forcing error.'; + await tester.pumpWidget( + MaterialApp( + home: MediaQuery( + data: const MediaQueryData(), + child: Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: Material( + child: Form( + child: ListView( + children: [ + DropdownButtonFormField( + key: fieldKey1, + items: + menuItems.map((String value) { + return DropdownMenuItem(value: value, child: Text(value)); + }).toList(), + onChanged: null, + autovalidateMode: AutovalidateMode.disabled, + ), + DropdownButtonFormField( + key: fieldKey2, + items: + menuItems.map((String value) { + return DropdownMenuItem(value: value, child: Text(value)); + }).toList(), + forceErrorText: forceErrorText, + onChanged: onChanged, + autovalidateMode: AutovalidateMode.disabled, + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + + expect(fieldKey1.currentState!.isValid, isTrue); + expect(fieldKey1.currentState!.hasError, isFalse); + expect(fieldKey2.currentState!.isValid, isFalse); + expect(fieldKey2.currentState!.hasError, isTrue); + }); + + testWidgets('forceErrorText overrides InputDecoration.error when both are provided', ( + WidgetTester tester, + ) async { + const String forceErrorText = 'Forcing error'; + const String decorationErrorText = 'Decoration'; + + await tester.pumpWidget( + MaterialApp( + home: MediaQuery( + data: const MediaQueryData(), + child: Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: Material( + child: Form( + child: DropdownButtonFormField( + items: + menuItems.map>((String value) { + return DropdownMenuItem(value: value, child: Text(value)); + }).toList(), + decoration: const InputDecoration(errorText: decorationErrorText), + forceErrorText: forceErrorText, + onChanged: null, + ), + ), + ), + ), + ), + ), + ), + ); + + expect(find.text(forceErrorText), findsOne); + expect(find.text(decorationErrorText), findsNothing); + }); }