go_form 1.8.0
go_form: ^1.8.0 copied to clipboard
A generic controller for managing state and validation of input fields in Flutter. Supports initial value, validation, errors, and focus.
GoForm #
Available Translations:
GoForm is a powerful library for managing forms in Flutter.
It allows you to dynamically create, validate, and manage form state
without the need to manually handle controllers for each field.
Features of GoForm #
-
Smart validation with minimal code
GoForm automatically validates input using standard validators,
eliminating the need to manually write validation logic for each field. -
Flexibility for any field types
Create any form elements — from simple text fields and checkboxes
to complex file pickers and dropdown menus.
GoForm seamlessly adapts to any UI structure. -
Centralized error management
Set and reset errors anywhere in your code,
without needing to usesetState()
.
Error display is fully automated and updates without unnecessary re-renders. -
Debounced value changes
Fields can debounce rapid input changes usingdebounceDuration
, reducing unnecessary processing or validations. -
Asynchronous validation
AddasyncValidator
to a field to perform validation that requires waiting for server responses or background checks.
UseformController.validateAsync()
to trigger validation across all fields. -
Advanced focus management
TheFormController
provides built-in methods for controlling focus between fields:focus(String name)
– focuses the field with the given name.unfocus(String name)
– removes focus from the specified field.unfocusAll()
– removes focus from all fields.focusNext(String name)
– moves focus to the next field.focusPrevious(String name)
– moves focus to the previous field.focusFirstError()
– focuses the first field that has a validation error.hasFocus(String name)
– returnstrue
if the field is currently focused.hasError(String name)
– returnstrue
if the field currently has an error.
Comparison of standard Flutter tools and GoForm #
Feature | GoForm | Standard Flutter |
---|---|---|
Field management | Fields are registered automatically | Each field requires a TextEditingController |
Field flexibility | Supports any fields (text, files, checkboxes) | Only TextFormField and standard widgets |
Error handling | Errors are set via FormController.setError() |
Errors can only be handled in validator |
Centralized state management | A single FormController manages the entire form |
Field states must be tracked manually |
Retrieving values | formController.getValues() returns a Map<String, dynamic> |
Requires accessing TextEditingController.text |
Resetting fields | formController.resetAllFields() |
Controllers must be cleared manually |
Handling server-side errors | Errors can be set using setError() |
Errors must be stored in setState() |
How to Install #
Add the dependency to pubspec.yaml
:
dependencies:
go_form: latest_version
Replace latest_version
with the latest version from pub.dev.
Quick Start #
Creating a Form with Dynamic Fields #
In DynamicForm
, simply pass a list of fields and a controller:
final _formController = FormController();
@override
Widget build(BuildContext context) {
return DynamicForm(
controller: _formController,
fields: [
GoTextInput(
name: 'email',
label: 'Email',
validator: (val) => val == null || val.isEmpty ? 'Enter your email' : null,
),
GoTextInput(
name: 'password',
label: 'Password',
validator: (val) => val == null || val.length < 6 ? 'Minimum 6 characters' : null,
),
],
);
}
Validation Check Before Submission #
void onSubmit() {
if (_formController.validate()) {
print(_formController.getValues()); // Retrieving form data
} else {
print(_formController.errors); // Displaying errors
}
}
Focus and Scrolling Example #
GoForm allows you to programmatically manage focus and scroll behavior:
GoTextInput(
name: 'email',
label: 'Email',
),
GoTextInput(
name: 'password',
label: 'Password',
),
To move focus to the next field:
ElevatedButton(
onPressed: () {
_formController.focusNext('email');
},
child: Text('Go to Password'),
);
To focus the first field with a validation error:
ElevatedButton(
onPressed: () async {
final isValid = await _formController.validateAsync();
if (!isValid) {
_formController.focusFirstError();
}
},
child: Text('Validate and Focus Error'),
);
To scroll to the first field with an error:
ElevatedButton(
onPressed: () async {
final isValid = await _formController.validateAsync();
if (!isValid) {
_formController.scrollToFirstErrorField();
}
},
child: Text('Validate and Scroll to Error'),
);
scrollToFirstErrorField()
works with DynamicForm
and assumes the form is wrapped in a scrollable container (e.g. SingleChildScrollView
).
Adding Errors #
void onLogin() async {
final response = await AuthAPI.login(
email: _formController.getFieldValue<String>('email'),
password: _formController.getFieldValue<String>('password'),
);
if (response.hasError) {
_formController.setError('email', response.errors['email']);
_formController.setError('password', response.errors['password']);
}
}
Resetting the Form #
_formController.resetAllFields
(); // Очистка значений
_formController.resetAllErrors
(); // Очистка ошибок
How to Create a Custom Field? #
Simply extend FormFieldModelBase<T>
and implement build()
:
class GoTextInput extends FormFieldModelBase<String> {
final String label;
GoTextInput({required super.name, super.validator, required this.label});
@override
Widget build(BuildContext context, FieldController controller) {
return TextField(
onChanged: controller.onChange,
controller: controller.textController,
decoration: InputDecoration(
labelText: label,
errorText: controller.error,
),
);
}
}
One-Time Initialization (onInit
) #
You can override the onInit
method inside your custom field to perform one-time setup logic.
This is useful for asynchronous operations, such as fetching initial data or triggering a service.
class MyCustomField extends FormFieldModelBase<String> {
@override
void onInit(FieldController<String> controller) {
controller.setValue('initial_value');
}
@override
Widget build(BuildContext context, FieldController<String> controller) {
// widget build logic here
}
}
About the author #
My telegram channel - @kotelnikoff_dev
Contributions #
Contributions are welcome! Feel free to open issues or create pull requests on the GitHub repository.