Add hasInteractedByUser getter in FormField (#131539)
Adds a getter to access the value of the private `RestorableBool _hasInteractedByUser`. *List which issues are fixed by this PR. You must list at least one issue.* Fixes #131538
This commit is contained in:
parent
685141bf3b
commit
e972d5a3f6
@ -423,6 +423,12 @@ class FormFieldState<T> extends State<FormField<T>> with RestorationMixin {
|
||||
/// True if this field has any validation errors.
|
||||
bool get hasError => _errorText.value != null;
|
||||
|
||||
/// Returns true if the user has modified the value of this field.
|
||||
///
|
||||
/// This only updates to true once [didChange] has been called and resets to
|
||||
/// false when [reset] is called.
|
||||
bool get hasInteractedByUser => _hasInteractedByUser.value;
|
||||
|
||||
/// True if the current value is valid.
|
||||
///
|
||||
/// This will not set [errorText] or [hasError] and it will not update
|
||||
|
@ -854,4 +854,90 @@ void main() {
|
||||
expect(fieldValue, '123456');
|
||||
expect(formKey.currentState!.validate(), isFalse);
|
||||
});
|
||||
|
||||
testWidgets('hasInteractedByUser returns false when the input has not changed', (WidgetTester tester) async {
|
||||
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
|
||||
|
||||
final Widget widget = MaterialApp(
|
||||
home: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
child: Material(
|
||||
child: TextFormField(
|
||||
key: fieldKey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(widget);
|
||||
|
||||
expect(fieldKey.currentState!.hasInteractedByUser, isFalse);
|
||||
});
|
||||
|
||||
testWidgets('hasInteractedByUser returns true after the input has changed', (WidgetTester tester) async {
|
||||
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
|
||||
|
||||
final Widget widget = MaterialApp(
|
||||
home: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
child: Material(
|
||||
child: TextFormField(
|
||||
key: fieldKey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(widget);
|
||||
|
||||
// initially, the field has not been interacted with
|
||||
expect(fieldKey.currentState!.hasInteractedByUser, isFalse);
|
||||
|
||||
// after entering text, the field has been interacted with
|
||||
await tester.enterText(find.byType(TextFormField), 'foo');
|
||||
expect(fieldKey.currentState!.hasInteractedByUser, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hasInteractedByUser returns false after the field is reset', (WidgetTester tester) async {
|
||||
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
|
||||
|
||||
final Widget widget = MaterialApp(
|
||||
home: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
child: Material(
|
||||
child: TextFormField(
|
||||
key: fieldKey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(widget);
|
||||
|
||||
// initially, the field has not been interacted with
|
||||
expect(fieldKey.currentState!.hasInteractedByUser, isFalse);
|
||||
|
||||
// after entering text, the field has been interacted with
|
||||
await tester.enterText(find.byType(TextFormField), 'foo');
|
||||
expect(fieldKey.currentState!.hasInteractedByUser, isTrue);
|
||||
|
||||
// after resetting the field, it has not been interacted with again
|
||||
fieldKey.currentState!.reset();
|
||||
expect(fieldKey.currentState!.hasInteractedByUser, isFalse);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user