formi 0.1.0 formi: ^0.1.0 copied to clipboard
A minimalist form builder, with null safetty and no dependencies
formi #
A minimalist form builder, with null safetty and no dependencies. Inspired by https://pub.dev/packages/flutter_form_builder.
Getting Started #
formi
does not include UI components but it will help you to build yours so you have full control.
You can check the example folder that contains some components to get you started.
1. Create a widget that extends FormiField #
For example you could create a Checkbox field like this
class FormiCheckbox extends FormiField<bool> {
final String title;
final String? subtitle;
FormiCheckbox({
required this.title,
required String name,
this.subtitle,
List<FormiValidator<bool>>? validators,
bool? initialValue,
bool? enabled = true,
}) : super(
name: name,
validators: validators,
initialValue: initialValue,
enabled: enabled,
builder: (field) {
return CheckboxListTile(
dense: true,
title: Text(title),
value: field.value ?? false,
onChanged: field.didChange,
contentPadding: EdgeInsets.zero,
);
},
);
}
2. Wrap your form in a Formi container #
Fields in Formi
needs a unique name
that is used to keep the value of the field
Formi(
child: Column(
children: [
Text('Privacy preferences'),
FormiCheckbox(
name: 'strict',
title: 'Strictly necesary',
subtitle: 'Required for the app to run as expected',
initialValue: true,
enabled: false,
),
FormiCheckbox(
name: 'analytics',
title: 'Analytics',
subtitle: 'Allow us to collect information about how you use the app',
),
OutlinedButton(
child: Text('Submit'),
onPressed: () {
final formiState = Formi.of(context);
formiState.save();
if (formiState.validate()) {
// Retrieve the form state with formiState.value
}
}
),
]
),
)
3. Add custom validators #
A validator is a function that takes the field value and the form state and returns:
- a
String
if there is an error null
otherwise
FormiValidator<T> required<T>(
BuildContext context, {
String? errorText,
}) {
return (value, state) {
if (value == null ||
(value is String && value.isEmpty) ||
(value is Iterable && value.isEmpty) ||
(value is Map && value.isEmpty)) {
return errorText ?? 'This field cannot be empty.';
}
return null;
};
}
4. Create more components to fit your needs #
For example the submit button could be written as
class FormiSubmit extends StatelessWidget {
final Widget Function(FormiState) builder;
FormiSubmit({required this.builder});
@override
Widget build(BuildContext context) {
final _formiState = Formi.of(context);
return builder(_formiState);
}
}