diff --git a/packages/flutter/lib/src/widgets/form.dart b/packages/flutter/lib/src/widgets/form.dart index 8fe5cf786b..dac0bf9c8d 100644 --- a/packages/flutter/lib/src/widgets/form.dart +++ b/packages/flutter/lib/src/widgets/form.dart @@ -357,7 +357,10 @@ class FormState extends State
{ if (!validateOnFocusChange || !field._focusNode.hasFocus) { final bool isFieldValid = field.validate(); hasError = !isFieldValid || hasError; - errorMessage += field.errorText ?? ''; + // Ensure that only the first error message gets announced to the user. + if (errorMessage.isEmpty) { + errorMessage = field.errorText ?? ''; + } if (invalidFields != null && !isFieldValid) { invalidFields.add(field); } diff --git a/packages/flutter/test/widgets/form_test.dart b/packages/flutter/test/widgets/form_test.dart index 5a3117d47d..1fc97db56f 100644 --- a/packages/flutter/test/widgets/form_test.dart +++ b/packages/flutter/test/widgets/form_test.dart @@ -139,44 +139,52 @@ void main() { await checkErrorText(''); }); - testWidgets('Should announce error text when validate returns error', (WidgetTester tester) async { - final GlobalKey formKey = GlobalKey(); - await tester.pumpWidget( - MaterialApp( - home: MediaQuery( - data: const MediaQueryData(), - child: Directionality( - textDirection: TextDirection.ltr, - child: Center( - child: Material( - child: Form( - key: formKey, - child: TextFormField( - validator: (_)=> 'error', - ), + testWidgets('Should announce only the first error message when validate returns errors', (WidgetTester tester) async { + final GlobalKey formKey = GlobalKey(); + await tester.pumpWidget( + MaterialApp( + home: MediaQuery( + data: const MediaQueryData(), + child: Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: Material( + child: Form( + key: formKey, + child: Column( + children: [ + TextFormField( + validator: (_) => 'First error message', + ), + TextFormField( + validator: (_) => 'Second error message', + ), + ], ), ), ), ), ), ), - ); - formKey.currentState!.reset(); - await tester.enterText(find.byType(TextFormField), ''); - await tester.pump(); + ), + ); + formKey.currentState!.reset(); + await tester.enterText(find.byType(TextFormField).first, ''); + await tester.pump(); - // Manually validate. - expect(find.text('error'), findsNothing); - formKey.currentState!.validate(); - await tester.pump(); - expect(find.text('error'), findsOneWidget); + // Manually validate. + expect(find.text('First error message'), findsNothing); + expect(find.text('Second error message'), findsNothing); + formKey.currentState!.validate(); + await tester.pump(); + expect(find.text('First error message'), findsOneWidget); + expect(find.text('Second error message'), findsOneWidget); - final CapturedAccessibilityAnnouncement announcement = tester.takeAnnouncements().single; - expect(announcement.message, 'error'); - expect(announcement.textDirection, TextDirection.ltr); - expect(announcement.assertiveness, Assertiveness.assertive); - - }); + final CapturedAccessibilityAnnouncement announcement = tester.takeAnnouncements().single; + expect(announcement.message, 'First error message'); + expect(announcement.textDirection, TextDirection.ltr); + expect(announcement.assertiveness, Assertiveness.assertive); +}); testWidgets('isValid returns true when a field is valid', (WidgetTester tester) async { final GlobalKey> fieldKey1 = GlobalKey>();