flutter_floc 0.0.0-dev.9
flutter_floc: ^0.0.0-dev.9 copied to clipboard
Flutter Floc helps you to create a form within a minute, reducing the boilerplate and providing helpers to link the view to the form state.
Introduction #
Flutter Floc helps you to create a form within a minute, reducing the boilerplate and providing helpers to link the view to the form state.
Motivations #
Creating forms always had been a repetitive task. In Dart specifically, there are some packages that helps you to reduce the needed boilerplate, for instance:
formz is a package providing a low-level API to manage an input state.
flutter_form_bloc is a package providing a high-level API to manage a form, with validations etc... The thing is, flutter_form_bloc is lacking of some functionality, one of them is testing.
We actually needed a strong and testable form manager and we love bloc. For this reason we created our own based on what flutter_form_bloc did.
Getting Started #
For help getting started with Flutter, view the online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.
Installation #
Add the flutter_floc package to the list of dependency of your Flutter Application (pubspec.yaml):
dependencies:
flutter:
sdk: flutter
flutter_floc: ^0.0.0-dev.8
Usage #
Creating a Form BLoC
- Create a new file named
register_form_bloc.dart(or whatever you like) - Define a class named
RegisterFormBlocthat extendsFormBloc:
// FormBloc<String>, String could be replaced
// by whatever form response type you like
class RegisterFormBloc extends FormBloc<String> {
}
- Define the form fields:
// username is required
static final username = FormField<String>(
name: 'username',
initialValue: '',
validators: [
FieldValidator(Validator.required),
],
);
// password is required and should be contains at least 6 characters
static final password = FormField<String>(
name: 'password',
initialValue: '',
validators: [
FieldValidator(Validator.required),
FieldValidator(Validator.min6Chars),
],
);
// confirmPassword is required and should have the same value as "password" field
static final confirmPassword = FormField<String>(
name: 'confirmPassword',
initialValue: '',
validators: [
FieldValidator(Validator.required),
FieldValidator(
Validator.confirmPassword,
fieldSubscriptions: [password],
),
],
);
- Add fields to the form inside the form constructor:
class RegisterFormBloc extends FormBloc<String> {
RegisterFormBloc() {
addFields([password, username, confirmPassword]);
}
}
- You can now override the
onSubmitmethod that will gets triggered when the form is submitted and valid:
@override
void onSubmit(fields) async {
// you can make HTTP calls here for example.
print(fields['username']);
print(fields['password']);
print(fields['confirmPassword']);
emitSuccess('success response : ok');
}
Now let's add some UI to display all these fancy things.
- Add a
FormBlocListener(which is based on BlocListener for those who came from theblocpackage) somewhere in your widgets tree.FormBlocListenerprovide some handlers that gets triggered during the form lifecycle (onSubmitting,onSuccess,onFailure):
class ExampleForm extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FormBlocListener<ExampleFormBloc, String>(
onSubmitting: (context, state) {
print('Loading...');
},
onSuccess: (context, state) {
print('Success !');
print(state.response);
},
onFailure: (context, state) {
print('Failure !');
print(state.response);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// Field are inside a TextFieldBlocBuilder
// that gets updated when the field state change.
TextFieldBlocBuilder<ExampleFormBloc>(
fieldName: 'username',
decoration: InputDecoration(hintText: 'Username'),
),
TextFieldBlocBuilder<ExampleFormBloc>(
fieldName: 'password',
obscureText: true,
decoration: InputDecoration(hintText: 'Password'),
),
TextFieldBlocBuilder<ExampleFormBloc>(
fieldName: 'confirmPassword',
obscureText: true,
decoration: InputDecoration(hintText: 'Confirm password'),
),
// Button that force fields validation.
MaterialButton(
onPressed: () {
context.read<ExampleFormBloc>().validate();
},
child: Text('Validate'),
),
// Button that triggers a submit on the form.
MaterialButton(
onPressed: () {
context.read<ExampleFormBloc>().submit();
},
child: Text('Submit'),
)
],
),
);
}
}
That's it! You've made your first FormBLoC.
Validators #
You can create simple validators, for example a 6minchars validator like this :
String min6Chars(String value, Map<String, dynamic> fields) {
if (value == null || value.isEmpty || value.runes.length < 6) {
return 'min 6 chars';
}
return null;
}
The return value is null if there is no error. Else it's a string where the return value is considered as the error key that will gets passed to the UI.
To add this validator to a field, simply add it to the field list validators:
static final 6minField = FormField<String>(
name: '6minField',
initialValue: '',
validators: [
FieldValidator(min6Chars),
],
);
Validators that depends on other value (confirm password case) #
A validator can depends on other fields value :
String confirmPassword(String value, Map<String, dynamic> fields) {
if (value != fields['password']) {
return 'different';
}
return null;
}
The second fields parameter contains the dependent fields. To add a dependency to a validator, simply define them into the validator fieldSubscriptions named parameter of confirmPassword:
static final confirmPassword = FormField<String>(
name: 'confirmPassword',
initialValue: '',
validators: [
FieldValidator(Validator.required),
FieldValidator(
Validator.confirmPassword,
// We can add other fields here
fieldSubscriptions: [password],
),
],
);
Testing your form #
TODO