diff --git a/packages/flutter/lib/src/widgets/form.dart b/packages/flutter/lib/src/widgets/form.dart index a0f28e8798e..7a8a29be5e1 100644 --- a/packages/flutter/lib/src/widgets/form.dart +++ b/packages/flutter/lib/src/widgets/form.dart @@ -466,6 +466,7 @@ class FormField extends StatefulWidget { super.key, required this.builder, this.onSaved, + this.onReset, this.forceErrorText, this.validator, this.errorBuilder, @@ -485,6 +486,10 @@ class FormField extends StatefulWidget { /// [FormState.save]. final FormFieldSetter? onSaved; + /// An optional method to call when the form field is reset via + /// [FormFieldState.reset]. + final VoidCallback? onReset; + /// An optional property that forces the [FormFieldState] into an error state /// by directly setting the [FormFieldState.errorText] property without /// running the validator function. @@ -631,6 +636,7 @@ class FormFieldState extends State> with RestorationMixin { _hasInteractedByUser.value = false; _errorText.value = null; }); + widget.onReset?.call(); Form.maybeOf(context)?._fieldDidChange(); } diff --git a/packages/flutter/test/widgets/form_test.dart b/packages/flutter/test/widgets/form_test.dart index 3a47aaea98a..cedc183c4b7 100644 --- a/packages/flutter/test/widgets/form_test.dart +++ b/packages/flutter/test/widgets/form_test.dart @@ -89,6 +89,32 @@ void main() { await checkText(''); }); + testWidgets('onReset callback is called', (WidgetTester tester) async { + final GlobalKey formKey = GlobalKey(); + bool resetCalled = false; + + await tester.pumpWidget( + MaterialApp( + home: Form( + key: formKey, + child: FormField( + builder: (_) => const SizedBox.shrink(), + onReset: () { + resetCalled = true; + }, + ), + ), + ), + ); + + expect(resetCalled, isFalse); + + formKey.currentState!.reset(); + await tester.pump(); + + expect(resetCalled, isTrue); + }); + testWidgets('Validator sets the error text only when validate is called', ( WidgetTester tester, ) async {