Keyed Field
import 'package:flutter/material.dart';
import 'package:fform/fform.dart';
enum EmailError {
empty,
invalidFormat,
}
class EmailField extends FFormField<String, EmailError> with KeyedField {
EmailField({required String value }) : super(value);
EmailError? validator(String value) {
if (value.isEmpty) return EmailError.empty;
if (isNotEmail(value)) return EmailError.invalidFormat;
return null;
}
}
class EmailForm extends StatefulWidget {
_EmailFormState createState() => _EmailFormState();
}
class _EmailFormState extends State<EmailForm> {
final EmailField _emailField = EmailField(value: '');
void dispose() {
_emailField.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Email Validation Form')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Enter your email:'),
SizedBox(height: 8),
TextField(
key: _emailField.key,
onChanged: (value) {
setState(() {
_emailField.value = value;
_emailField.check();
});
},
decoration: InputDecoration(
hintText: 'Email',
errorText: _emailField.isInvalid ? _getErrorText() : null,
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _submitForm,
child: Text('Submit'),
),
],
),
),
);
}
String? _getErrorText() {
if (_emailField.exception == EmailError.empty) {
return 'Email cannot be empty';
} else if (_emailField.exception == EmailError.invalidFormat) {
return 'Invalid email format';
}
return null;
}
void _submitForm() {
if (_emailField.isValid) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Email is valid!')),
);
} else {
Scrollable.ensureVisible(
_emailField.key.currentContext!,
alignment: 0.2,
duration: const Duration(milliseconds: 500),
);
}
}
}
Explanation:​
-
GlobalKey
fromKeyedField
:
TheEmailField
class now includes akey
property from theKeyedField
mixin, which is aGlobalKey
. This key uniquely identifies the widget in the widget tree. -
Binding
key
toTextField
:
Thekey
property of theEmailField
instance is passed directly to theTextField
widget, allowing you to reference and manage the state of this specific form field widget in the widget tree. -
Usage in the Form:
- When you create the
EmailField
, it automatically has a unique key that you can use to refer to it, which could be helpful for focusing, scrolling, or handling form actions programmatically. - The
key
can also be used in scenarios where you need to programmatically focus or manipulate theTextField
widget tied to this form field.
- When you create the
This allows you to have both real-time validation feedback and access to the widget's state using the unique GlobalKey
.