Flutter Form Builder

repository·main·Indexed 23 days ago

https://github.com/flutter-form-builder-ecosystem/flutter_form_builder

A Flutter package that streamlines the creation of complex data collection forms. It provides ready-made input widgets (such as FormBuilderTextField, FormBuilderDropdown, and FormBuilderDateTimePicker), built-in validation support, and easy value extraction via FormBuilderState. The library reduces boilerplate code for building forms, reacting to field changes, and implementing custom form fields using FormBuilderField.

Tokens
11.7K
Snippets
14
Records
52
Agent score
71%

What's inside flutter_form_builder

  1. Overview of Flutter Form Builder

    main

    flutter_form_builder is a package designed to simplify the creation of data collection forms in Flutter. It reduces boilerplate code required for building forms, validating fields, reacting to changes, and collecting final user input.

    Key capabilities include:

    • Creating forms with various input types.
    • Easily retrieving form values.
    • Applying validators to input fields.
    • Reacting to changes in form fields and validation states.
  2. Build a custom field with FormBuilderField

    main

    To create a custom input that integrates with the FormBuilder ecosystem (supporting validation, resetting, and value tracking), use the FormBuilderField widget. You must provide a builder function that returns a widget. Use field.didChange(newValue) within your custom widget to update the form state.

    FormBuilderField(
      name: "name",
      validator: FormBuilderValidators.compose([
        FormBuilderValidators.required(),
      ]),
      builder: (FormFieldState<dynamic> field) {
        return InputDecorator(
          decoration: InputDecoration(
            labelText: "Select option",
            errorText: field.errorText,
          ),
          child: Container(
            height: 200,
            child: CupertinoPicker(
              itemExtent: 30,
              children: options.map((c) => Text(c)).toList(),
              onSelectedItemChanged: (index) {
                field.didChange(options[index]);
              },
            ),
          ),
        );
      },
    ),
  3. Customize iOS launch screen assets

    main

    To change the image used for the iOS launch screen, you can either replace the image files directly in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory or use Xcode to manage the assets.

    To use Xcode:

    1. Open the iOS project using open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  4. Explore form building patterns in the example project

    main

    The example project is organized into specific source files that demonstrate different advanced form use cases. You can find these implementations in the lib/sources/ directory:

    • complete_form.dart: Demonstrates all available input types.
    • signup_form.dart: A practical implementation of a sign-up form.
    • dynamic_fields.dart: Shows how to add or remove fields at runtime.
    • conditional_fields.dart: Demonstrates how to show or hide fields based on other field values.
    • submit_button.dart: Shows how to manage submit button state based on form state and validation.
    • related_fields.dart: Demonstrates forms with interdependent field values.
    • grouped_radio_checkbox.dart: Shows selection inputs with grouping.
    • decorated_radio_checkbox.dart: Shows custom styling for selection fields.
    • custom_fields.dart: Demonstrates how to implement custom form fields.
  5. Basic usage of FormBuilder

    main

    To use flutter_form_builder, wrap your input fields in a FormBuilder widget and provide it with a GlobalKey<FormBuilderState>. This key allows you to access the form's state, such as its values and validation methods.

    Each input field must have a unique name property to identify its value within the form state.

    final _formKey = GlobalKey<FormBuilderState>();
    
    FormBuilder(
        key: _formKey,
        child:  FormBuilderTextField(
            name: 'text',
            onChanged: (val) {
                print(val); // Print the text value write into TextField
            },
        ),
    )
  6. Run the Flutter Form Builder example application

    main

    To run the comprehensive example application that demonstrates various form building patterns (such as dynamic fields, conditional fields, and custom fields), follow these steps in your terminal:

    1. Navigate to the example directory.
    2. Fetch the required dependencies.
    3. Execute the application using flutter run.
    cd example
    flutter pub get
    flutter run
  7. Configure GroupedCheckbox layout orientations

    main

    The GroupedCheckbox widget supports four layout modes via the orientation parameter:

    1. OptionsOrientation.auto: Uses an OverflowBar with MainAxisAlignment.spaceEvenly to distribute items.
    2. OptionsOrientation.vertical: Arranges items in a Column inside a SingleChildScrollView (vertical scrolling).
    3. OptionsOrientation.horizontal: Arranges items in a Row inside a SingleChildScrollView (horizontal scrolling).
    4. OptionsOrientation.wrap: Uses a Wrap widget inside a SingleChildScrollView, allowing items to flow to the next line/column based on available space.
  8. Use the FormBuilder widget to manage form state

    main

    FormBuilder is the primary container for managing a collection of form fields. It tracks field values, validation states, and provides methods to save, validate, or reset the entire form.

    Key Properties

    • initialValue: A Map<String, dynamic> of field names to their starting values. Local field initialValue settings take precedence over this.
    • onChanged: A callback triggered whenever any field in the form changes. Note that all form fields will rebuild when this is called.
    • enabled: If false, all form fields are disabled and won't accept input.
    • skipDisabled: If true, the final form value will not include values from fields where enabled is false. Defaults to false.
    • clearValueOnUnregister: If true, the form will not keep internal values from disposed FormBuilderFields. Useful for dynamic forms.
    • autovalidateMode: Controls when field validation error text is updated.

    Accessing Form State

    You can access the FormBuilderState from anywhere within the FormBuilder widget tree using the FormBuilder.of(context) method.

  9. Migrate from v9 to v10

    main

    If you are upgrading from version 9 to version 10, note the following breaking changes:

    • Invalidation: invalidateField and invalidateFirstField methods on FormBuilderState have been removed. Use fields[name]?.invalidate(errorText) or fields.first.invalidate(errorText) instead.
    • Focus: canRequestFocus on FormBuilderTextField is deprecated. Use FocusNode.canRequestFocus instead.
    • Enabled Property: FormBuilderField.decoration.enabled is replaced by FormBuilderField.enabled.
    • Renames (can be fixed with dart fix --apply):
      • FormBuilderChoiceChip $\rightarrow$ FormBuilderChoiceChips
      • FormBuilderFilterChip $\rightarrow$ FormBuilderFilterChips (Note: maxChips property removed)
      • FormBuilderDateTimePicker (Note: resetIcon property removed)
      • FormBuilder (Note: onPopInvoked property removed)
  10. Perform conditional validation

    main

    You can implement conditional validation by writing a custom validator function that inspects the value of other fields in the form via the FormBuilderState.

    FormBuilderRadioGroup(
      name: 'my_language',
      options: [
        FormBuilderFieldOption(value: 'Dart'),
        FormBuilderFieldOption(value: 'Other'),
      ],
    ),
    FormBuilderTextField(
      name: 'specify',
      validator: (val) {
        if (_formKey.currentState.fields['my_language']?.value == 'Other' &&
            (val == null || val.isEmpty)) {
          return 'Kindly specify your language';
        }
        return null;
      },
    ),
  11. Reset specific fields

    main

    To reset a specific field (e.g., via a clear button in the suffix or suffixIcon of an InputDecoration), call reset() on that field's state using its GlobalKey or by accessing it through the FormBuilderState.fields map.

    // Using Form Key to reset a field
    IconButton(
      icon: const Icon(Icons.close),
      onPressed: () {
        _formKey.currentState!.fields['gender']?.reset();
      },
    )
    
    // Using Field Key to reset a field
    IconButton(
      onPressed: () => textFieldKey.currentState?.didChange(null),
      icon: const Icon(Icons.clear),
    )
  12. Format date and time values in FormBuilderDateTimePicker

    main

    When using FormBuilderDateTimePicker, you can specify how the date/time is displayed and stored using the format parameter. This parameter expects a DateFormat object from the intl package.

    import 'package:intl/intl.dart';
    
    FormBuilderDateTimePicker(
      name: 'date',
      inputType: InputType.date,
      format: DateFormat('yyyy-MM-dd'),
    )