[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.
|
/// True if this field has any validation errors.
|
||||||
bool get hasError => _errorText != null;
|
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.
|
/// Calls the [FormField]'s onSaved method with the current value.
|
||||||
void save() {
|
void save() {
|
||||||
if (widget.onSaved != null)
|
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
|
/// Calls [FormField.validator] to set the [errorText]. Returns true if there
|
||||||
/// were no errors.
|
/// were no errors.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [isValid], which passively gets the validity without setting
|
||||||
|
/// [errorText] or [hasError].
|
||||||
bool validate() {
|
bool validate() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_validate();
|
_validate();
|
||||||
|
@ -137,6 +137,100 @@ void main() {
|
|||||||
await checkErrorText('');
|
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 {
|
testWidgets('Multiple TextFormFields communicate', (WidgetTester tester) async {
|
||||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
|
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user