Last updated:
0 purchases
flutter forms
English |
Français
As with Angular, reactive forms are now on Flutter !
By using flutter_forms, you will be able to simplify your code and validation of you forms.
Summary #
Getting Started
Requirements
Dependencies
FormBuilder
FormGroup
Add control to a FormGroup
Remove control from a FormGroup
Check if a control exists into a FormGroup
Get a FormGroup child
Get a FormArray child
Get a FormControl child
FormArray
Add item to a FormArray
Remove item from a FormArray
FormControl
Set a value
Clone a form element
How to add a reactive form into an application?
Define a model file
Initialize library
Define a new basic form
Add inputs
How to add a reactive form with multiple steps into an application?
What about validators?
Add validators
Create validators
Providers and Consumers
FormProvider
ReactiveFormStateProvider
FormGroupProvider
FormArrayProvider
FormControlProvider
MultipleStepFormStateIndexerProvider
See more examples
Getting Started #
flutter_forms is very easy to use. First, you should learn to use Flutter.
Please, read the online documentation before using this library.
You will find tutorials, code labs, sample projects... Everything you need to be autonomous.
Requirements #
Dart SDK: >=2.7.0 <3.0.0
Flutter: >= 1.17.0
Dependencies #
You must install all these dependencies to use flutter_forms :
dependencies:
flutter:
sdk: flutter
build_runner: any
reflectable: ^2.2.9
flutter_forms: ^1.0.0
copied to clipboard
Then, run flutter packages get command on the console.
FormBuilder #
flutter_forms is inspired by Angular reactive forms.
Of course, FormBuilder is the starting point of form creation.
Here is the way to build a form :
ReactiveFormBuilder form_builder = new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'first_name': new FormControl<String>(value: null, validators: []),
'last_name': new FormControl<String>(value: null, validators: []),
},
validators: [],
),
);
copied to clipboard
A form is created and automatically instantiated when you add it to ReactiveForm widget. It provides a complete tree of form elements to use.
But it's a simplified version of Angular reactive forms.
As for Angular reactive forms, flutter_forms can create dynamic forms.
Lets see all these points together !
FormGroup #
First you have the FormGroup. This one is a group of FormGroup, FormArray and FormControl.
You must use them for complex forms, with multiple levels.
Imagine you have a to set your profile. You could have two distinct parts into this form.
ReactiveFormBuilder form_builder = new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'personal': new FormGroup(
controls: {
'first_name': new FormControl<String>(value: null, validators: []),
'last_name': new FormControl<String>(value: null, validators: []),
},
validators: [],
),
'social_links': new FormGroup(
controls: {
'github': new FormControl<String>(value: null, validators: []),
'facebook': new FormControl<String>(value: null, validators: []),
},
validators: [],
)
},
validators: [],
),
);
copied to clipboard
Add control to a FormGroup #
How to add a sub part of you form dynamically ?
Here is a short code to add a FormGroup in the children collection of a FormGroup :
FormGroup root = new FormGroup(controls: {}, validators: []);
FormGroup child = new FormGroup(controls: {}, validators: []);
root.addControl('child', child);
copied to clipboard
Here is a short code to add a FormArray in the children collection of a FormGroup :
FormGroup root = new FormGroup(controls: {}, validators: []);
FormArray child = new FormArray(groups: [], validators: []);
root.addControl('child', child);
copied to clipboard
Finally, here is a short code to add a FormControl in the children collection of a FormGroup :
FormGroup root = new FormGroup(controls: {}, validators: []);
FormControl<String> child = new FormControl<String>(value: null, validators: []);
root.addControl('child', child);
copied to clipboard
Remove control from a FormGroup #
Here is a short code to remove a FormGroup from the children collection of a FormGroup :
FormGroup root = new FormGroup(
controls: {
'child': new FormGroup(controls: {}, validators: []),
},
validators: [],
);
root.removeControl('child');
copied to clipboard
That function will trigger the validation engine and update the form to display errors if there are.
Here is a short code to remove a FormArray from the children collection of a FormGroup :
FormGroup root = new FormGroup(
controls: {
'child': new FormArray(groups: [], validators: []),
},
validators: [],
);
root.removeControl('child');
copied to clipboard
That function will trigger the validation engine and update the form to display errors if there are.
Finally, here is a short code to remove a FormControl from the children collection of a FormGroup :
FormGroup root = new FormGroup(
controls: {
'child': new FormControl<String>(value: null, validators: []),
},
validators: [],
);
root.removeControl('child');
copied to clipboard
That function will trigger the validation engine and update the form to display errors if there are.
Check if a control exists into a FormGroup #
How to check if a control does exist into a FormGroup ?
FormGroup root = new FormGroup(controls: {}, validators: []);
bool exists = root.containsControl('child');
copied to clipboard
Get a FormGroup child #
How to get a FormGroup child ?
DON'T DO THIS !
FormGroup root = new FormGroup(
controls: {
'child': new FormGroup(controls: {}, validators: []),
},
validators: [],
);
FormGroup child = root.controls['child'] as FormGroup;
copied to clipboard
DO THIS !
FormGroup root = new FormGroup(
controls: {
'child': new FormGroup(controls: {}, validators: []),
},
validators: [],
);
FormGroup child = root.getFormGroup('child');
copied to clipboard
Get a FormArray child #
How to get a FormArray child ?
DON'T DO THIS !
FormGroup root = new FormGroup(
controls: {
'child': new FormControl<String>(value: null, validators: []),
},
validators: [],
);
FormControl<String> child = root.controls['child'] as FormControl<String>;
copied to clipboard
DO THIS !
FormGroup root = new FormGroup(
controls: {
'child': new FormControl<String>(value: null, validators: []),
},
validators: [],
);
FormControl<String> child = root.getFormControl<String>('child');
copied to clipboard
Get a FormControl child #
How to get a FormArray child ?
DON'T DO THIS !
FormGroup root = new FormGroup(
controls: {
'child': new FormArray(groups: [], validators: []),
},
validators: [],
);
FormArray child = root.controls['child'] as FormArray;
copied to clipboard
DO THIS !
FormGroup root = new FormGroup(
controls: {
'child': new FormArray(groups: [], validators: []),
},
validators: [],
);
FormArray child = root.getFormArray('child');
copied to clipboard
FormArray #
Next you have the FormArray. This one is a collection of FormGroup only.
This a difference with Angular's library. I disagree with the fact a FormArray can contain directly FormControl items.
In my opinion, Angular FormArray is too permissive. Developer could try to add FormGroup and FormControl items into the same FormArray.
This should not be possible, even if an exception is thrown after.
So, here is the way to declare a FormArray :
ReactiveFormBuilder form_builder = new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'social_links': new FormArray(
groups: [
new FormGroup(
controls: {
'social_network': new FormControl<String>(value: 'github', validators: []),
'url': new FormControl<String>(value: 'https://github.com/maxime-aubry/', validators: []),
},
validators: [],
),
],
validators: [],
)
},
validators: [],
),
);
copied to clipboard
As you can see, you can register complex data into an item of a FormArray.
Add item to a FormArray #
Add an item to a FormArray is easy.
Remember that you can add FormGroup items only.
Here is the way to add an item :
FormArray array = new FormArray(groups: [], validators: []);
FormGroup child = new FormGroup(controls: {}, validators: []);
array.addGroup(child);
copied to clipboard
That function will trigger the validation engine and update the form to display errors if there are.
Remove item from a FormArray #
Here is the way to remove an item :
FormArray array = new FormArray(
groups: [
// an item is here
],
validators: [],
);
FormGroup child = new FormGroup(controls: {}, validators: []);
array.removeGroup(child);
copied to clipboard
That function will trigger the validation engine and update the form to display errors if there are.
This part is a little confuse because you don't see how to get an item from the form array. Lets see that later.
FormControl #
What would be a form if we didn't use FormControl ?
This is the way to store data, while FormGroup and FormArray are used for the structure !
FormControl are done to support a limited list of data types :
DateTime.
num (Number).
int.
double.
String.
bool.
List of DateTime.
List of num.
List of int.
List of double.
List of String.
List of bool.
Uint8List, Uint16List, Uint32List, Uint64List, Int8List, Int16List, Int32List and Int64List (for buffer arrays).
enums.
list of enums.
If you try to use a disallowed type, an exception will be thrown.
This list could evolve later.
Here is the way to declare a FormControl with String generic type :
ReactiveFormBuilder form_builder = new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'first_name': new FormControl<String>(value: 'Maxime', validators: []),
},
validators: [],
),
);
copied to clipboard
Set a value #
Here is the way to set a value to a FormControl :
FormControl<String> control = new FormControl<String>(value: null, validators: []);
control.setValue('my value');
copied to clipboard
That function will trigger the validation engine and update the form to display errors if there are.
Clone a form element #
Clone a form element is a very important point of flutter_forms.
Imagine you are modifying an item of your form, as a sub FormGroup. You changes values, and you decide to click on cancel button.
Rollback your values could be hard !
So, you should clone the part of the form you want to update, and apply those changes later if you want.
When you clone a form element, you clone the full tree of ReactiveFormBuilder, so you can use you validators to compare a value with another.
Here is an example :
ReactiveFormBuilder form_builder = new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'first_name': new FormControl<String>(value: 'Maxime', validators: []),
},
validators: [],
),
);
FormControl<String> child = form_builder.group.getFormControl<String>('first_name');
FormControl<String> clone = child.getClone();
copied to clipboard
Whether for FormGroup, FormArray or FormControl, you can use the same getClone() method.
How to add a reactive form into an application? #
Now we studied the basics of flutter_forms, lets see how to create a form into a Flutter application.
Define a model file #
First, you should define a model file.
This one will contain all you enums, if you will use them.
Into the ./lib/models.dart, here are the different steps we will do :
define a namespace for models
import flutter_forms
define a main() method (for reflectable)
define you enums
If you does not define your enums here, they will be refused with FormControl later. An exception will be thrown.
Please, use @flutterFormsValidator notation to declare the content.
@flutterFormsValidator
library example.models;
import 'package:flutter_forms/flutter_forms.dart';
void main() {}
@flutterFormsValidator
enum EGender { male, female }
copied to clipboard
Use this command line to get the file to get a new file named models.reflectable.dart into a flutter application project.
> flutter pub run build_runner build
copied to clipboard
Initialize library #
Next, into the main.dart file, you must initialize the namespace to import.
Here, you import example.models from ./lib/models.reflectable.dart.
import 'package:example/models.reflectable.dart';
import 'package:flutter_forms/flutter_forms.dart';
void main() {
initializeReflectable();
LibraryInitializer.initialize(libraryName: 'example.models');
runApp(new MyApp());
}
copied to clipboard
Define a new basic form #
Here we are. We are going to define our new form.
Into your widget, start by defining a [ReactiveForm] object.
[formBuilder] property receives the form builder.
@override
Widget build(BuildContext context) {
return ReactiveForm(
formBuilder: this._getFormBuilder(),
builder: (context, _) {
return new Container();
},
);
}
ReactiveFormBuilder _getFormBuilder() => new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'first_name': new FormControl<String>(value: 'Maxime', validators: []),
'last_name': new FormControl<String>(value: 'AUBRY', validators: []),
},
validators: [],
),
);
copied to clipboard
We just created a new form with two fields, first_name and last_name.
Add inputs #
Next, let add inputs to display on our screen.
@override
Widget build(BuildContext context) {
return ReactiveForm(
formBuilder: this._getFormBuilder(),
builder: (context, _) {
// here, we get the root level of the form builder.
FormGroup root = context.watchFormGroup();
return new Scaffold(
appBar: new AppBar(title: Text("Reactive form")),
body: new Padding(
padding: EdgeInsets.all(5.0),
child: new Column(
children: [
// here, we add inputs for first_name and last_name fields
this._inputText(root.getFormControl<String>('first_name'), 'first name'),
this._inputText(root.getFormControl<String>('last_name'), 'last name'),
],
),
),
floatingActionButton: new FloatingActionButton(
child: Icon(Icons.done),
onPressed: () async {
// here, we get the form state and validate the form
ReactiveFormState formState = context.readFormState();
if (await formState.validate()) {
// Data treatment and post to server here...
}
},
),
);
},
);
}
Widget _inputText(FormControl<String> formControl, String label) =>
new TextFormField(
decoration: InputDecoration(labelText: label),
keyboardType: TextInputType.text,
controller: new TextEditingController(text: formControl.value),
// here, we set the value into the FormControl
onChanged: (String value) async => await formControl.setValue(value),
// here, we set the value into the FormControl
onSaved: (String value) async => await formControl.setValue(value),
// here, we display the error if there is one
validator: (String value) => formControl.error?.message,
);
copied to clipboard
How to add a reactive form with multiple steps into an application? #
flutter_forms supports forms with multiples steps !
You must add your forms into a container that will assemble all form states.
Lets see an easy example.
Here is the main screen :
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: Text("Reactive multiple steps form")),
body: new MultipleStepFormContainer(
builder: (context, _) {
return new Stepper(
onStepContinue: () async {
// here we get all steps names
List<String> stepsNames =
context.readMultipleStepFormStateIndexer().keys.toList();
// here we get the form state for the targeted step name
ReactiveFormState formState = context.readFormState(
step: stepsNames[currentStep],
);
// here we validate the current step
if (await formState.validate()) {
// Data treatment and post to server here...
}
},
);
},
),
);
}
copied to clipboard
Here is a step :
@override
Widget build(BuildContext context) {
return new ReactiveForm(
step: 'profile', // here we define the step name
formBuilder: this._getFormBuilder(),
builder: (context, _) {
FormGroup root = context.watchFormGroup();
// form content here
return new Container();
},
);
}
ReactiveFormBuilder _getFormBuilder() => new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'first_name': new FormControl<String>(value: null, validators: []),
'last_name': new FormControl<String>(value: null, validators: []),
},
validators: [],
),
);
copied to clipboard
Here is another step :
@override
Widget build(BuildContext context) {
return new ReactiveForm(
step: 'social_links', // here we define the step name
formBuilder: this._getFormBuilder(),
builder: (context, _) {
FormGroup root = context.watchFormGroup();
// form content here
return new Container();
},
);
}
ReactiveFormBuilder _getFormBuilder() => new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'social_links': new FormArray(groups: [], validators: []),
},
validators: [],
),
);
copied to clipboard
What about validators? #
What would be this library without validators ? NOTHING !
Add validators #
So, here is a list of available validators :
Common :
Validator
Description
Progress
Required
Validate a FormGroup, FormArray and FormControl. Checks if a FormGroup is not null and contains controls. Checks if a FormArray is not null and contains items. Checks if a FormControl is not null. If this one is a string, checks if it's not an empty string.
done
FormGroup :
There are not validators for FormGroup for this time.
FormArray :
Validator
Description
Progress
NbItems
Checks if a FormArray has a valid length.
done
FormControls :
Validator
Description
Progress
Email
Checks if a value is a valid email.
done
EqualToDateTime
Checks if a datetime value is equal to another.
done
EqualToDouble
Checks if a double value is equal to another.
done
EqualToInt
Checks if a int value is equal to another.
done
EqualToNumber
Checks if a number value is equal to another.
done
EqualToString
Checks if a string value is equal to another.
done
FileMimeType
Checks if a file has an allowed mime type.
done
FileSize
Checks if a file has an allowed size.
done
GreaterOrEqualToDateTime
Checks if a datetime value is greater or equal to another.
done
GreaterOrEqualToDouble
Checks if a double value is greater or equal to another.
done
GreaterOrEqualToInt
Checks if a int value is greater or equal to another.
done
GreaterOrEqualToNumber
Checks if a number value is greater or equal to another.
done
GreaterOrEqualToString
Checks if a string value is greater or equal to another.
done
GreaterThanDateTime
Checks if a datetime value is greater than another.
done
GreaterThanDouble
Checks if a double value is greater than another.
done
GreaterThanInt
Checks if a int value is greater than another.
done
GreaterThanNumber
Checks if a number value is greater than another.
done
GreaterThanString
Checks if a string value is greater than another.
done
ImageSize
Checks if the image width and height.
done
InText
Checks if the text is contained into another text.
done
MembershipPassword
Checks if the password has a good format according to the settings.
done
MultiSelect
Checks if value is a selection of items contained into a list of items.
done
NbValues
Checks if a array value has a valid length.
done
NotEqualToDateTime
Checks if a datetime value is not equal to another.
done
NotEqualToDouble
Checks if a double value is not equal to another.
done
NotEqualToInt
Checks if a int value is not equal to another.
done
NotEqualToNumber
Checks if a number value is not equal to another.
done
NotEqualToString
Checks if a string value is not equal to another.
done
RangeOfDateTime
Checks if a datetime value is between min and max values.
done
RangeOfDouble
Checks if a double value is between min and max values.
done
RangeOfInt
Checks if a int value is between min and max values.
done
RangeOfNumber
Checks if a number value is between min and max values.
done
RangeOfString
Checks if a string value is between min and max values.
done
RegularExpression
Checks if a value has a good format according to a regular expression.
done
SingleSelect
Checks if value is an item contained into a list of items.
done
SmallerOrEqualToDateTime
Checks if a datetime value is smaller or equal to another.
done
SmallerOrEqualToDouble
Checks if a double value is smaller or equal to another.
done
SmallerOrEqualToInt
Checks if a int value is smaller or equal to another.
done
SmallerOrEqualToNumber
Checks if a number value is smaller or equal to another.
done
SmallerThanString
Checks if a string value is smaller or equal to another.
done
SmallerThanDateTime
Checks if a datetime value is smaller than another.
done
SmallerThanDouble
Checks if a double value is smaller than another.
done
SmallerThanInt
Checks if a int value is smaller than another.
done
SmallerThanNumber
Checks if a number value is smaller than another.
done
SmallerThanString
Checks if a string value is smaller than another.
done
StringLength
Checks if a string value is a valid length.
done
Url
Checks if a value has a good URL format..
done
How can we add validators to a form element ?
You can add these functions to FormGroup, FormArray and FormControls.
These three classes has a validators property.
So, let see how to do this.
ReactiveFormBuilder _getFormBuilder() => new ReactiveFormBuilder(
group: new FormGroup(
controls: {
'first_name': new FormControl<String>(
value: 'Maxime',
validators: [
Required(error: 'first name is required'),
StringLength(min: 3, max: 50, error: 'first name must have between 3 and 50 characters.')
],
),
'last_name': new FormControl<String>(
value: 'AUBRY',
validators: [
Required(error: 'last name is required'),
StringLength(min: 3, max: 50, error: 'last name must have between 3 and 50 characters.')
],
),
},
validators: [],
),
);
copied to clipboard
Next time you will validate the form, these validators will be run.
Be careful, these validators will be run in this the order you will add them.
So, don't add StringLength validator before Required validator for example.
Create validators #
You easily can create you own validators.
Custom validators must override one of these three classes :
FormGroupValidatorAnnotation for FormGroup validators.
FormArrayValidatorAnnotation for FormArray validators.
FormControlValidatorAnnotation for FormControl validators.
FormValidatorAnnotation for validators that are common for these three form elements.
Here is a basic example for a FormGroup validator :
class CustomValidator extends FormGroupValidatorAnnotation {
const CustomValidator({
@required String error,
}) : super(error: error);
@override
Future<bool> isValid(FormGroup control) async {
// TODO: implement isValid
throw UnimplementedError();
}
}
copied to clipboard
Here is a basic example for a FormArray validator :
class CustomValidator extends FormArrayValidatorAnnotation {
const CustomValidator({
@required String error,
}) : super(error: error);
@override
Future<bool> isValid(FormArray control) async {
// TODO: implement isValid
throw UnimplementedError();
}
}
copied to clipboard
For FormControl validators, you must use generic type !
Here is a basic example for a FormControl validator :
class CustomValidator extends FormControlValidatorAnnotation<String> {
const CustomValidator({
@required String error,
}) : super(error: error);
@override
Future<bool> isValid(FormControl<String> control) async {
// TODO: implement isValid
throw UnimplementedError();
}
}
copied to clipboard
Providers and Consumers #
flutter_forms uses Provider library to provide and consume form elements into your widgets.
For almost each provider of flutter_forms, you can use Consumers (they are widgets), watchers and readers.
If you want to use Consumers, watchers or readers, data must be provided before.
Watchers are done to get form elements and rebuild widgets than use them when their value changes.
Readers are done to get form elements without rebuilding widgets than use them when their value changes.
Consumers can make reading difficult.
The last thing to know is watchers and Consumers do exactly the same thing.
FormProvider #
FormProvider is used inside ReactiveForm widget. Thanks to him, you are able to use Consumers, watchers and readers without defining it yourself.
Except if you need to go to a new route, you will must share elements with the new widget.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new FormProvider(
providers: [
new FormGroupProvider.value(value: existingFormGroup),
],
child: new Destination(),
),
),
);
copied to clipboard
ReactiveFormStateProvider #
ReactiveFormStateProvider is used inside ReactiveForm widget. Thanks to him, you are able to use Consumers, watchers and readers without defining it yourself.
ReactiveFormState watcher :
ReactiveFormState formState = context.watchFormState();
copied to clipboard
ReactiveFormState reader :
ReactiveFormState formState = context.readFormState();
copied to clipboard
ReactiveFormState consumer :
child: new ReactiveFormStateConsumer(
builder: (context, formState, child) {
return new Container();
},
);
copied to clipboard
FormGroupProvider #
FormGroupProvider is used inside ReactiveForm widget. Thanks to him, you are able to use Consumers, watchers and readers without defining it yourself.
But, if you want to consume a sub form element, in the sub level of the root, you must provide it.
For example, here is a form. Root level is provided, thanks to ReactiveForm widget.
If we want to use Consumers, watchers or readers on a sub form element, use FormGroupProvider.value on it !
@override
Widget build(BuildContext context) {
return ReactiveForm(
formBuilder: this._getFormBuilder(),
builder: (context, _) {
// here, we get the root level of the form builder.
FormGroup root = context.watchFormGroup();
// here, we provide the child FormGroup
return new FormGroupProvider.value(
value: root.getFormGroup('child'),
builder: (context, _) {
FormGroup child = context.watchFormGroup();
return new Container();
}
);
},
);
}
copied to clipboard
FormGroup watcher :
FormGroup formGroup = context.watchFormGroup();
copied to clipboard
FormGroup reader :
FormGroup formGroup = context.readFormGroup();
copied to clipboard
FormGroup consumer :
child: new FormGroupConsumer(
builder: (context, formGroup, child) {
return new Container();
},
);
copied to clipboard
FormArrayProvider #
FormArray is always a sub form element of root level. If you want to consume it, you must provide it.
For example, here is a form. Root level is provided, thanks to ReactiveForm widget.
If we want to use Consumers, watchers or readers on a sub form element, use FormArrayProvider.value on it !
@override
Widget build(BuildContext context) {
return ReactiveForm(
formBuilder: this._getFormBuilder(),
builder: (context, _) {
// here, we get the root level of the form builder.
FormGroup root = context.watchFormGroup();
// here, we provide the child FormArray
return new FormArrayProvider.value(
value: root.getFormArray('child'),
builder: (context, _) {
FormArray child = context.watchFormArray();
return new Container();
}
);
},
);
}
copied to clipboard
FormArray watcher :
FormArray formArray = context.watchFormArray();
copied to clipboard
FormArray reader :
FormArray formArray = context.readFormArray();
copied to clipboard
FormArray consumer :
child: new FormArrayConsumer(
builder: (context, formArray, child) {
return new Container();
},
);
copied to clipboard
FormControlProvider #
FormControl is always a sub form element of root level. If you want to consume it, you must provide it.
For example, here is a form. Root level is provided, thanks to ReactiveForm widget.
If we want to use Consumers, watchers or readers on a sub form element, use FormControlProvider.value on it !
@override
Widget build(BuildContext context) {
return ReactiveForm(
formBuilder: this._getFormBuilder(),
builder: (context, _) {
// here, we get the root level of the form builder.
FormGroup root = context.watchFormGroup();
// here, we provide the child FormControl
return new FormControlProvider.value(
value: root.getFormControl<String>('child'),
builder: (context, _) {
FormControl<String> child = context.watchFormControl<String>();
return new Container();
}
);
},
);
}
copied to clipboard
FormControl watcher :
FormControl<String> formControl = context.watchFormControl<String>();
copied to clipboard
FormControl reader :
FormControl<String> formControl = context.readFormControl<String>();
copied to clipboard
FormControl consumer :
child: new FormControlConsumer<String>(
builder: (context, formControl, child) {
return new Container();
},
);
copied to clipboard
MultipleStepFormStateIndexerProvider #
MultipleStepFormStateIndexer is used only inside form with multiple steps.
Its role is to assemble all form state inside an indexer. So, Stepper will be able to target the good form state that you should use.
Use it when you want to validate a step :
@override
Widget build(BuildContext context) {
return new MultipleStepFormContainer(
builder: (context, _) {
return new Stepper(
type: StepperType.horizontal,
steps: this.steps,
currentStep: currentStep,
onStepContinue: () async {
// here we get all steps names
List<String> stepsNames =
context.readMultipleStepFormStateIndexer().keys.toList();
// here we get the form state for the targeted step name
ReactiveFormState formState = context.readFormState(
step: stepsNames[currentStep],
);
// here we validate the current step
if (await formState.validate()) {
// Data treatment and post to server here...
}
},
onStepTapped: (step) => goTo(step),
onStepCancel: cancel,
);
},
);
}
copied to clipboard
FormControl watcher :
MultipleStepFormStateIndexer indexer = context.watchMultipleStepFormStateIndexer();
copied to clipboard
FormControl reader :
MultipleStepFormStateIndexer indexer = context.readMultipleStepFormStateIndexer();
copied to clipboard
See more examples #
I invite you to study example project.
Example project uses libraries :
date_time_picker.
file_picker.
flutter_slidable.
smart_select.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.