[Form] Add is valid to FormState (#48948)
This commit is contained in:
parent
4c5aef63a9
commit
e7c90057c7
@ -349,6 +349,16 @@ class FormFieldState<T> extends State<FormField<T>> {
|
||||
/// True if this field has any validation errors.
|
||||
bool get hasError => _errorText != null;
|
||||
|
||||
/// True if the current value is valid.
|
||||
///
|
||||
/// This will not set [errorText] or [hasError] and it will not update
|
||||
/// error display.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [validate], which may update [errorText] and [hasError].
|
||||
bool get isValid => widget.validator?.call(_value) == null;
|
||||
|
||||
/// Calls the [FormField]'s onSaved method with the current value.
|
||||
void save() {
|
||||
if (widget.onSaved != null)
|
||||
@ -365,6 +375,11 @@ class FormFieldState<T> extends State<FormField<T>> {
|
||||
|
||||
/// Calls [FormField.validator] to set the [errorText]. Returns true if there
|
||||
/// were no errors.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [isValid], which passively gets the validity without setting
|
||||
/// [errorText] or [hasError].
|
||||
bool validate() {
|
||||
setState(() {
|
||||
_validate();
|
||||
|
@ -137,6 +137,100 @@ void main() {
|
||||
await checkErrorText('');
|
||||
});
|
||||
|
||||
testWidgets('isValid returns true when a field is valid', (WidgetTester tester) async {
|
||||
final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>();
|
||||
final GlobalKey<FormFieldState<String>> fieldKey2 = GlobalKey<FormFieldState<String>>();
|
||||
const String validString = 'Valid string';
|
||||
String validator(String s) => s == validString ? null : 'Error text';
|
||||
|
||||
Widget builder() {
|
||||
return MaterialApp(
|
||||
home: MediaQuery(
|
||||
data: const MediaQueryData(devicePixelRatio: 1.0),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
child: Material(
|
||||
child: Form(
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
key: fieldKey1,
|
||||
initialValue: validString,
|
||||
validator: validator,
|
||||
autovalidate: true
|
||||
),
|
||||
TextFormField(
|
||||
key: fieldKey2,
|
||||
initialValue: validString,
|
||||
validator: validator,
|
||||
autovalidate: true
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(builder());
|
||||
|
||||
expect(fieldKey1.currentState.isValid, isTrue);
|
||||
expect(fieldKey2.currentState.isValid, isTrue);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'isValid returns false when the field is invalid and does not change error display',
|
||||
(WidgetTester tester) async {
|
||||
final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>();
|
||||
final GlobalKey<FormFieldState<String>> fieldKey2 = GlobalKey<FormFieldState<String>>();
|
||||
const String validString = 'Valid string';
|
||||
String validator(String s) => s == validString ? null : 'Error text';
|
||||
|
||||
Widget builder() {
|
||||
return MaterialApp(
|
||||
home: MediaQuery(
|
||||
data: const MediaQueryData(devicePixelRatio: 1.0),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
child: Material(
|
||||
child: Form(
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
key: fieldKey1,
|
||||
initialValue: validString,
|
||||
validator: validator,
|
||||
autovalidate: false,
|
||||
),
|
||||
TextFormField(
|
||||
key: fieldKey2,
|
||||
initialValue: '',
|
||||
validator: validator,
|
||||
autovalidate: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(builder());
|
||||
|
||||
expect(fieldKey1.currentState.isValid, isTrue);
|
||||
expect(fieldKey2.currentState.isValid, isFalse);
|
||||
expect(fieldKey2.currentState.hasError, isFalse);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('Multiple TextFormFields communicate', (WidgetTester tester) async {
|
||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
|
||||
|
Loading…
x
Reference in New Issue
Block a user