fform
FForm ist ein Dart-Paket zum Erstellen von Formularen mit vielen Feldern und Validierungen.
FForm ist ein hochwertiges Flutter-Paket, das die Erstellung und Verwaltung von Formularen erleichtern soll, mit vereinfachter Feldvalidierung. Es bietet zwei Hauptkomponenten: FFormField und FFormBuilder, die gemeinsam Einfachheit und Flexibilität bei der Formularverarbeitung in Flutter-Anwendungen bieten.
^1.17.1{"sdk":"flutter"}^1.9.1{"sdk":"flutter"}^3.0.0Englischer Projektschnappschuss. Aktuelle Inhalte auf GitHub.
Logo Frame
First things first, let's get the FForm package into your Flutter project. Add FForm to your pubspec.yaml file under dependencies:
dependencies:
fform: ^latest_version
Don't forget to run flutter pub get in your terminal to install the package.
FForm is a high-level Flutter package designed to make form creation and management a breeze, with simplified field validation. It offers two main components: FFormField and FFormBuilder, that together bring ease and flexibility to your form handling in Flutter apps.
🧱 Core (Logic and Form Model)
🧩 Widget (UI Binding Widgets)
🎯 Mixin (Additional Behavior for Fields)
https://raw.githubusercontent.com/AlexHCJP/fform/HEAD/pictures/structure.png
| https://raw.githubusercontent.com/AlexHCJP/fform/HEAD/pictures/1.gif | https://raw.githubusercontent.com/AlexHCJP/fform/HEAD/pictures/2.gif | https://raw.githubusercontent.com/AlexHCJP/fform/HEAD/pictures/3.gif |
| https://raw.githubusercontent.com/AlexHCJP/fform/HEAD/pictures/4.gif |
FFormFieldFFormField is a base class for all form fields, supporting values, on-the-fly validation, and change handling. It provides a set of getters and methods to manage the field state, including checking the field's validity, retrieving the current value, and handling exceptions.
enum EmailError {
empty,
not;
@override
String toString() {
switch (this) {
case empty:
return 'emailEmpty';
case not:
return 'invalidFormatEmail';
default:
return 'invalidFormatEmail';
}
}
}
class EmailField extends FFormField<String, EmailError> {
EmailField({required String value}) : super(value);
@override
EmailError? validator(value) {
if (value.isEmpty) return EmailError.empty;
return null;
}
}
FFormFForm is a base class for creating custom form classes with specific fields and validation rules. It provides a set of getters and methods to manage the form state, including checking the form's validity, retrieving answers, and handling exceptions.
This is a simple example of how to create a form with a single field. You can extend the FForm class to create custom forms with specific fields and validation rules.
class LoginForm extends FForm {
EmailField email;
LoginForm({
required this.email,
}): super(fields: [email]);
}
This is a more complex example of how to create a form with multiple fields. You can extend the FForm class to create custom forms with specific fields and validation rules.
class Form extends FForm {
List<Form> forms;
Form({
required this.forms,
}): super(subForms: forms);
}
FFormBuilderFFormBuilder is a widget that constructs and manages the form state, utilizing streams to refresh the UI dynamically as data changes. It provides a builder function that takes the form and returns a widget tree based on the form's state.
This is an example of how to use FFormBuilder to create a form with a single field. The builder function takes the form as a parameter and returns a widget tree based on the form's state.
void _submit() {
if(_form.check()) { // .isValid or .isInvalid start rebuild in FFormBuilder and returned boolean
print('Form Valid');
};
}
@override
Widget build(BuildContext context) {
return FFormBuilder<LoginForm>(
form: _form,
builder: (context, form, child) {
EmailField email = form.email; // or FFormProvider.of<LoginForm>(context).get<NameField>()
return Column(
children: [
TextField(
key: email.key,
controller: _emailController,
decoration: InputDecoration(
labelText: 'Email',
errorText: email.exception.toString(),
),
),
ElevatedButton(
onPressed: _submit,
child: const Text('Submit'),
),
],
);
},
);
}
You can use ListenableBuilder to rebuild only the field that has changed,
but you can use FFormProvider to rebuild all fields in the form.
void _submit() {
if(_form.check()) { // .isValid or .isInvalid start rebuild in FFormBuilder and returned boolean
print('Form Valid');
};
}
@override
Widget build(BuildContext context) {
return ListenableBuilder<LoginForm>(
listenable: _form,
builder: (context, form, child) {
EmailField email = form.email; // or FFormProvider.of<LoginForm>(context).get<NameField>()
return Column(
children: [
TextField(
key: email.key,
controller: _emailController,
decoration: InputDecoration(
labelText: 'Email',
errorText: email.exception.toString(),
),
),
ElevatedButton(
onPressed: _submit,
child: const Text('Submit'),
),
],
);
},
);
}
FFormProviderFFormProvider is a widget that allows you to access the form in the widget tree without passing it as a parameter.
FFormBuilder<LoginForm>(
form: _form,
builder: (context, form) {
FFormProvider.of<LoginForm>(context).email; // or form.email;
FFormProvider.of<LoginForm>(context).get<NameField>(); // or form.get<NameField>();
return YourForm();
},
)
FFormException is a base class for creating custom exceptions for form fields. It allows you to define custom validation rules and error messages for form fields, enabling you to handle complex validation scenarios with ease.
You can create a custom exception class that extends FFormException to define specific validation rules and error messages for a form field.
class PasswordValidationException extends FFormException {
final bool isMinLengthValid;
final bool isSpecialCharValid;
final bool isNumberValid;
PasswordValidationException({
required this.isMinLengthValid,
required this.isSpecialCharValid,
required this.isNumberValid,
});
@override
bool get isValid => isMinLengthValid && isSpecialCharValid && isNumberValid;
}
class PasswordField extends FFormField<String, PasswordValidationException> {
PasswordField(String value) : super(value);
@override
PasswordValidationException? validator(String value) {
final validator = FFormValidator(value);
return PasswordValidationException(
isMinLengthValid: validator.isMinLength(8),
isSpecialCharValid: validator.isHaveSpecialChar,
isNumberValid: validator.isHaveNumber,
);
}
}
FFormObserverFFormObserver is a widget that allows you to observe the form state and trigger side effects based on the form's state changes. It provides a builder function that takes the form as a parameter and returns a widget tree based on the form's state.
class MyFFormObserver extends FFormObserver {
@override
void check(FForm form) {
if (kDebugMode) {
print('Form has been checked and is ${form.isValid ? 'valid' : 'invalid'}');
}
}
}
class EmailField extends FFormField<String, EmailError> with KeyedField {
EmailField({required String value}) : super(value);
@override
EmailError? validator(value) {
if (value.isEmpty) return EmailError.empty;
return null;
}
}
// and get GlobalKey -> form.email.key
class EmailField extends FFormField<String, EmailError> with AsyncField<String, EmailError> {
EmailField({required String value}) : super(value);
@override
EmailError? validator(value) {
if (value.isEmpty) return EmailError.empty;
return null;
}
@override
Future<EmailError?> asyncValidator(value) async {
await Future.delayed(Duration(seconds: 1));
if (!value.contains('@')) return EmailError.not;
return null;
}
}
// final field = EmailField();
// if(await field.check()) {
//
// }
class EmailField extends FFormField<String, EmailError> with CachedField<String, EmailError> {
EmailField({required String value}) : super(value);
@override
EmailError? validator(value) {
if (value.isEmpty) return EmailError.empty;
return null;
}
}
class EmailField extends FFormField<String, EmailError> with FocusField<String, EmailError> {
EmailField({required String value}) : super(value);
@override
EmailError? validator(value) {
if (value.isEmpty) return EmailError.empty;
return null;
}
}
// final field = EmailField();
// if(field.check()) {
// ....
// } else {
// field.focus.requestFocus();
// }
FFormStatusFFormStatus is an enum that represents the various states of a form (FForm) during its lifecycle. It helps track the form's status, such as whether it's idle, processing, successfully validated, or has encountered errors.
initial: The default state of the form before any action is taken.loading: Indicates that the form is currently processing, such as during validation or submission.success: Indicates that the form has successfully completed its operation with no validation errors.exception: Indicates that the form has encountered errors, such as validation failures.switch(_form.status) {
FFormStatus.initial => print('initial'),
FFormStatus.loading => print('loading'),
FFormStatus.success => print('success'),
FFormStatus.exception => print('exception'),
};
Codecov