Skip to main content

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:​

  1. GlobalKey from KeyedField:
    The EmailField class now includes a key property from the KeyedField mixin, which is a GlobalKey. This key uniquely identifies the widget in the widget tree.

  2. Binding key to TextField:
    The key property of the EmailField instance is passed directly to the TextField widget, allowing you to reference and manage the state of this specific form field widget in the widget tree.

  3. 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 the TextField widget tied to this form field.

This allows you to have both real-time validation feedback and access to the widget's state using the unique GlobalKey.