Create better Forms in Flutter using flutter_form_builder

Flutter Aug 6, 2023

Forms are essential for gathering information from users in mobile applications. In this post, we will learn how to create better forms in Flutter using the flutter_form_builder package. We will start by installing the necessary components and understanding how to use different form fields like checkboxes, dropdowns, and date pickers to collect user input. Then, we will look into validation using the form_builder_validators package, which helps ensure users provide accurate information. Finally, we will cover all the available fields from the flutter_form_builder package.

Installing

To get started, we need to install the flutter_form_builder and form_builder_validators packages into our project. The installation process is simple. Just execute the following command: flutter pub add flutter_form_builder form_builder_validators.

Once the command is executed, make sure to check your pubspec.yaml file for the added dependencies. You should see the flutter_form_builder and form_builder_validators packages included in the dependencies section, like this:

dependencies:
  flutter:
    sdk: flutter
  flutter_form_builder: ^9.1.0
  form_builder_validators: ^9.0.0

Implementation

With these packages integrated into our project, we can start by creating our first form, see the following code:

import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FormPage(),
    );
  }
}

class FormPage extends StatelessWidget {
  final GlobalKey<FormBuilderState> _formKey = GlobalKey<FormBuilderState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Form Builder Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: FormBuilder(
          key: _formKey,
          child: Column(
            children: [
              FormBuilderTextField(
                name: 'email',
                decoration: InputDecoration(labelText: 'Email'),
              ),
              SizedBox(height: 10),
              FormBuilderDropdown(
                name: 'gender',
                decoration: InputDecoration(labelText: 'Gender'),
                items: ['Male', 'Female', 'Other']
                    .map((gender) => DropdownMenuItem(
                  value: gender,
                  child: Text(gender),
                ))
                    .toList(),
              ),
              SizedBox(height: 10),
              FormBuilderDateTimePicker(
                name: 'birthdate',
                decoration: InputDecoration(labelText: 'Birthdate'),
                inputType: InputType.date,
                initialDate: DateTime.now(),
                initialValue: DateTime.now(),
                firstDate: DateTime(1900),
                lastDate: DateTime.now(),
              ),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.saveAndValidate()) {
                    showDialog(
                      context: context,
                      builder: (context) => AlertDialog(
                        title: Text('Form data'),
                        content: Text(
                          _formKey.currentState!.value.entries
                              .map((entry) => '${entry.key}: ${entry.value}')
                              .join('\n'),
                          style: TextStyle(fontSize: 18),
                        ),
                        actions: [
                          ElevatedButton(
                            onPressed: () => Navigator.of(context).pop(),
                            child: Text('OK', style: TextStyle(fontSize: 20)),
                          ),
                        ],
                      ),
                    );
                  }
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

In this code snippet, we created a simple application that has a MaterialApp that has the FormPage widget set as the home property. The FormPage widget has a private _formKey variable that is set to GlobalKey<FormBuilderState>(). This variable is needed inside the FormBuilder widget.

The FormBuilder widget is used to wrap the form fields and provide the form state management. The form fields are created using FormBuilderTextField, FormBuilderDropdown, and FormBuilderDateTimePicker. Each form field has a name, which will be used to identify the field and retrieve its value later.

When the user clicks the "Submit" button, the form data is saved and validated using the _formKey.currentState!.saveAndValidate() method. If the data is valid, an AlertDialog is shown, displaying the form data. The form data is accessed from the _formKey.currentState!.value map.

flutter_demonstrating_form_builder

Validation

Data validation is important when creating forms because it ensures that users provide the right information that is needed. The form_builder_validators package helps us set up rules for validation. For example, we can make sure certain fields are filled, check that email addresses are in the correct format, and set limits on numbers. These rules help users know if they have entered the data correctly, and it stops them from sending wrong or incomplete information.

FormBuilderTextField(
  name: 'email',
  decoration: InputDecoration(labelText: 'Email'),
  validator: FormBuilderValidators.compose([
    FormBuilderValidators.required(),
    FormBuilderValidators.email(),
  ]),
),

In this code snippet, we added the validator property and used the FormBuilderValidators.compose function to set validations. The function takes a list of FormBuilderValidators:

  1. FormBuilderValidators.required: The field cannot be left empty.
  2. FormBuilderValidators.email: The entered text should be in a valid email format.

When the form is submitted, the FormBuilder widget automatically validates this field based on these rules. If the validation passes, the entered email is considered valid and can be accessed from the form state using the identifier "email" _formKey.currentState!.value['email'].

flutter_demonstrating_form_builder_with_validation

All possible validation rules

  1. creditCard: Validates that the field's value is a valid credit card number.
  2. date: Validates that the field's value is a valid date.
  3. email: Validates that the field contains a valid email address format.
  4. equal(Object value): Validates that the field's value is equal to the value of another field specified by value.
  5. equalLength(int length): Validates that the field's value is equal to the provided length.
  6. integer: Validates that the field's value is a valid integer.
  7. ip: Validates that the field's value is a valid IP address.
  8. match(String pattern): Validates that the field's value matches the provided regex pattern.
  9. max(num max): Validates that the field's value is less than or equal to the provided number.
  10. maxLength(int maxLength): Validates that the field's value has a maximum length of maxLength.
  11. maxWordsCount(int maxCount): Validates that the field's value is less than or equal to the provided maximum count.
  12. mim(num min): Validates that the field's value is greater than or equal to the provided number.
  13. minLength(int minLength): Validates that the field's value has a minimum length of minLength.
  14. minWordsCount(int minCount): Validates that the field's value is greater than or equal to the provided minimum count.
  15. notEqual(Object value): Validates that the field's value is not equal to the provided value.
  16. numeric: Validates that the field's value is a valid numeric value.
  17. required: Validates that the field is not empty and has a value.
  18. url: Validates that the field's value is a valid URL.

Available fields

The flutter_form_builder package gives us many ready-to-use form fields for different types of data and ways users interact with them. We have checkboxes, dropdowns, date pickers, and slider inputs, among others. We can easily use these fields in our forms. They are flexible and can be customized to suit our application's requirements, making it simple to create interactive and engaging forms. All the available fields are listed below with an example:

1. FormBuilderCheckbox

Represents a single checkbox field.

FormBuilderCheckbox(
  name: 'checkbox_field',
  title: Text('Checkbox'),
  initialValue: false,
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_check_box_field

2. FormBuilderCheckboxGroup

Represents a list of checkboxes for multiple selections.

FormBuilderCheckboxGroup(
  name: 'checkbox_group_field',
  options: [
    FormBuilderFieldOption(value: 'Option 1'),
    FormBuilderFieldOption(value: 'Option 2'),
    FormBuilderFieldOption(value: 'Option 3'),
  ],
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_check_box_group

3. FormBuilderChoiceChip

Creates a chip that acts like a radio button for selecting one choice from a list.

FormBuilderChoiceChip(
  name: 'choice_chip_field',
  options: [
    FormBuilderChipOption(value: 'Option 1'),
    FormBuilderChipOption(value: 'Option 2'),
    FormBuilderChipOption(value: 'Option 3'),
  ],
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_choice_chip

4. FormBuilderDateRangePicker

Allows users to select a range of dates.

FormBuilderDateRangePicker(
  name: 'date_range_field',
  onChanged: (value) {},
  firstDate: DateTime.parse('2021-01-01'),
  lastDate: DateTime.parse('2023-12-31'),
),

flutter_demonstrating_form_builder_date_range_picker

5. FormBuilderDateTimePicker

Allows users to input Date, Time, or DateTime values.

FormBuilderDateTimePicker(
  name: 'date_time_field',
  inputType: InputType.date,
  initialDate: DateTime.now(),
  initialValue: DateTime.now(),
  firstDate: DateTime(1900),
  lastDate: DateTime.now(),
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_date_time_picker

6. FormBuilderDropdown

Presents a dropdown list for selecting a single value from a list.

FormBuilderDropdown(
  name: 'dropdown_field',
  items: ['Option 1', 'Option 2', 'Option 3']
      .map((option) => DropdownMenuItem(value: option, child: Text(option)))
      .toList(),
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_drop_down

7. FormBuilderFilterChip

Creates a chip that acts as a checkbox for filtering purposes.

FormBuilderFilterChip(
  name: 'filter_chip_field',
  options: [
    FormBuilderChipOption(value: 'Option 1'),
    FormBuilderChipOption(value: 'Option 2'),
    FormBuilderChipOption(value: 'Option 3'),
  ],
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_filter_chip

8. FormBuilderRadioGroup

Allows users to select one value from a list of Radio Widgets.

FormBuilderRadioGroup(
  name: 'radio_group_field',
  options: [
    FormBuilderFieldOption(value: 'Option 1'),
    FormBuilderFieldOption(value: 'Option 2'),
    FormBuilderFieldOption(value: 'Option 3'),
  ],
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_radio_group

9. FormBuilderRangeSlider

Allows users to select a range from a range of values using a slider.

FormBuilderRangeSlider(
  name: 'range_slider_field',
  min: 0,
  max: 100,
  initialValue: RangeValues(20, 80),
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_range_slider

10. FormBuilderSlider

Represents a slider for selecting a numerical value.

FormBuilderSlider(
  name: 'slider_field',
  min: 0,
  max: 100,
  initialValue: 50,
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_slider

11. FormBuilderSwitch

Provides an on/off switch field.

FormBuilderSwitch(
  name: 'switch_field',
  initialValue: false,
  title: Text('Switch'),
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_switch

12. FormBuilderTextField

Represents a Material Design text field input for various data types.

FormBuilderTextField(
  name: 'text_field',
  decoration: InputDecoration(labelText: 'Enter Text'),
  onChanged: (value) {},
),

flutter_demonstrating_form_builder_text_field

Conclusion

The flutter_form_builder package is a helpful tool for creating user-friendly forms with ease. By using form fields like checkboxes, dropdowns, and date pickers, you can easily collect user information. Additionally, with the form_builder_validators, you can make sure users fill in the required fields correctly and enter valid data. These packages make it simple to build advanced and interactive forms in Flutter, improving the overall experience for your users.

Tags