A multi select form field using alert dialog to select multiple items with checkboxes and showing as chips.

Overview

Donate - Buy Me A Coffee

Multi select form field

A multi select form field using alert dialog to select multiple items with checkboxes and showing as chips.

Demo

Features

  • Can be used as regular form field.
  • Simple to implement.
  • Simple and intuitive to use in the app.
  • Provides validation of data.
  • Provides requirement of the field.
  • Customizable texts.
  • Follows the app theme and colors.
  • Upgraded to Null Safety.

Customization Parameters [MultiFormField]

Parameter Description
title Widget Set Title of MultiSelectTextFormField.
hintWidget Widget Set Hint Text of MultiSelectTextFormField.
required bool Add Selection is Compulsary or not.
errorText String Error String to be Displayed
dataSource List List of Data as DataSource To Select.
textField String Key Param from List (DataSource).
valueField String Value Param From List (DataSource).
okButtonLabel String* POsitive Button Label String.
cancelButtonLabel String* Negative Button Label String.
fillColor Color Widget Changes background color of FormField

Customization [Selection Dialog]

Parameter Description
Shape ShapeBorder Customizes the Shape Of AlertDialog
dialogTextStyle TextStyle Customizes the TextStyle Of AlertDialog
checkBoxCheckColor Color Customizes the CheckColor
checkBoxActiveColor Color Customizes the CheckBoxActiveColor

Customization [Selection Chip]

Parameter Description
chipLabelStyle TextStyle Customizes the TextStyle Of Selected Chip
chipBackGroundColor Color Customizes the Color Of Selected Chip

Minimal Example

MultiSelectFormField(
                  autovalidate: false,
                  chipBackGroundColor: Colors.red,
                  chipLabelStyle: TextStyle(fontWeight: FontWeight.bold),
                  dialogTextStyle: TextStyle(fontWeight: FontWeight.bold),
                  checkBoxActiveColor: Colors.red,
                  checkBoxCheckColor: Colors.green,
                  dialogShapeBorder: RoundedRectangleBorder(
                      borderRadius: BorderRadius.all(Radius.circular(12.0))),
                  title: Text(
                    "Title Of Form",
                    style: TextStyle(fontSize: 16),
                  ),
                  dataSource: [
                    {
                      "display": "Running",
                      "value": "Running",
                    },
                    {
                      "display": "Climbing",
                      "value": "Climbing",
                    },
                    {
                      "display": "Walking",
                      "value": "Walking",
                    },
                  ],
                  textField: 'display',
                  valueField: 'value',
                  okButtonLabel: 'OK',
                  cancelButtonLabel: 'CANCEL',
                  hintWidget: Text('Please choose one or more'),
                  initialValue: _myActivities,
                  onSaved: (value) {
                    if (value == null) return;
                    setState(() {
                      _myActivities = value;
                    });
                  },
                ),

Example

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

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

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

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List? _myActivities;
  late String _myActivitiesResult;
  final formKey = new GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
    _myActivities = [];
    _myActivitiesResult = '';
  }

  _saveForm() {
    var form = formKey.currentState!;
    if (form.validate()) {
      form.save();
      setState(() {
        _myActivitiesResult = _myActivities.toString();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('MultiSelect Formfield Example'),
      ),
      body: Center(
        child: Form(
          key: formKey,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Container(
                padding: EdgeInsets.all(16),
                child: MultiSelectFormField(
                  autovalidate: AutovalidateMode.disabled,
                  chipBackGroundColor: Colors.blue,
                  chipLabelStyle: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
                  dialogTextStyle: TextStyle(fontWeight: FontWeight.bold),
                  checkBoxActiveColor: Colors.blue,
                  checkBoxCheckColor: Colors.white,
                  dialogShapeBorder: RoundedRectangleBorder(
                      borderRadius: BorderRadius.all(Radius.circular(12.0))),
                  title: Text(
                    "My workouts",
                    style: TextStyle(fontSize: 16),
                  ),
                  validator: (value) {
                    if (value == null || value.length == 0) {
                      return 'Please select one or more options';
                    }
                    return null;
                  },
                  dataSource: [
                    {
                      "display": "Running",
                      "value": "Running",
                    },
                    {
                      "display": "Climbing",
                      "value": "Climbing",
                    },
                    {
                      "display": "Walking",
                      "value": "Walking",
                    },
                    {
                      "display": "Swimming",
                      "value": "Swimming",
                    },
                    {
                      "display": "Soccer Practice",
                      "value": "Soccer Practice",
                    },
                    {
                      "display": "Baseball Practice",
                      "value": "Baseball Practice",
                    },
                    {
                      "display": "Football Practice",
                      "value": "Football Practice",
                    },
                  ],
                  textField: 'display',
                  valueField: 'value',
                  okButtonLabel: 'OK',
                  cancelButtonLabel: 'CANCEL',
                  hintWidget: Text('Please choose one or more'),
                  initialValue: _myActivities,
                  onSaved: (value) {
                    if (value == null) return;
                    setState(() {
                      _myActivities = value;
                    });
                  },
                ),
              ),
              Container(
                padding: EdgeInsets.all(8),
                child: ElevatedButton(
                  child: Text('Save'),
                  onPressed: _saveForm,
                ),
              ),
              Container(
                padding: EdgeInsets.all(16),
                child: Text(_myActivitiesResult),
              )
            ],
          ),
        ),
      ),
    );
  }
}

License

This project is licensed under the BSD License. See the LICENSE file for details.

Comments
  •  multiselect_formfield not working with flutter 2.8.0

    multiselect_formfield not working with flutter 2.8.0

    Hi folks, Please update this package. I am using 0.16 (latest). It was running fine with flutter 2.5.3, now I have upgraded to 2.8.0 and this package is not working with android/ios, It says "Error: No named parameter with the name 'autovalidate'.". Please see the attached screenshot and solve it soon. Thanks. Capture

    opened by syedbilal07 8
  • Bugfix: When providing default value on load the validator is always null

    Bugfix: When providing default value on load the validator is always null

    Bug Report: https://github.com/cetorres/multiselect_formfield/issues/9

    Comments for reviewer:

    • I removed all intellij files and .gitignored. This seems to be recommended. I also .gitignored some files that were auto generated in my project for iOS.
    • Fixed a warning with the validator that said you must always return something. Returning null is the proper thing to return if passed validation: https://flutter.dev/docs/cookbook/forms/validation
    • Made a breaking change. I removed value. Seems like its more standard to have initialValue. I essentially just replaced your value for the built in state.value. In which initialvalue automatically sets state.value as you can see in https://github.com/flutter/flutter/blob/e0c63cd35e15e407a80dc44281cc392535fcce25/packages/flutter/lib/src/widgets/form.dart#L422

    I appreciate your consideration for including. Thanks for creating this library.

    opened by DavidCorrado 7
  • Added Customization Features

    Added Customization Features

    Hello, I have Added various UI Related Improvements/Features in your existing plugin, Updated ReadMe File Containing Details Of All New things Added Like, :

    • Added More Features Like Title/Hint as Widget, Chip Customizations(color/label)
    • Dialog Customizations - Dialog textStyle Find More details on readMe.md
    opened by SurajLad 3
  • let users override default fillColor and border

    let users override default fillColor and border

    Hi. Really like this widget! Would like to use it in an app we're building, but have a need to override the input decoration -- fillColor and border.

    opened by megberry 2
  • Compability with Flutter 2.8.0

    Compability with Flutter 2.8.0

    changes autovalidate to autovalidateMode property on FormField because of its removal in 2.8.0 after its deprecation, refering to https://github.com/flutter/flutter/pull/90292

    opened by FariJan 1
  • When providing default value on load the validator is always null

    When providing default value on load the validator is always null

    Summary: So if you use your example code. Then set a default value of the drop down. If you press save the form validation returns null thus failing validation.

    Steps to reproduce

    1. So in your example if you change the empty array here https://github.com/cetorres/multiselect_formfield/blob/99b313e78d403d349472a2def28ffd021dd5b4db/example/lib/main.dart#L28 To be _myActivities = ["Running"];
    2. Load the example and press save Expected: Validation passes and shows array below. Actual: Validation fails because value in validation is null
    opened by DavidCorrado 0
  • How to update selected values from outside

    How to update selected values from outside

    Is there a way to update the value being selected from outside of multiselect_formfield?

    Example. I am looking to implement a clear button and clear multiple edit items at once.

    opened by kanari3 0
  • No items can be selected if a text has been written into a TextFormField immediately before (focus still active)

    No items can be selected if a text has been written into a TextFormField immediately before (focus still active)

    The two widgets:

    CustomScrollView(shrinkWrap: true, slivers: [
                      SliverToBoxAdapter(
                          child: Column(children: [
                        Container(
                          height: 1,
                          color: kColorUltraLightGrey,
                        ),
                        SizedBox(height: 28),
                        EditTextField(
                          label: Utils.t(context, 'interim_note_form.note'),
                          padding: EdgeInsets.symmetric(horizontal: 16),
                          isExpandable: true,
                          controller: _messageController,
                        ),
                        FileUpload(
                          label: Utils.t(context, 'interim_note_form.action_add_photo'),
                          fileType: FileType.image,
                          didSelectFiles: (files) => _files = files,
                          files: _files,
                        ),
                        Padding(
                          padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                          child: Stack(
                            key: multiSelectFormFieldKey,
                            children: [
                              MultiSelectFormField(
                                title: Text(Utils.t(context, 'interim_note_form.concerned_modules'), style: TextStyle(fontSize: 11, color: kColorLabel)),
                                fillColor: kColorBackgroundFormField,
                                dataSource: _moduleOptions ?? [],
                                initialValue: _selectedModuleIds,
                                textField: 'display',
                                valueField: 'value',
                                hintWidget: Padding(
                                  padding: const EdgeInsets.only(bottom: 4.0),
                                  child: Text(Utils.t(context, 'form.choose'), style: kTextStyleBody.copyWith(color: kColorLabel)),
                                ),
                                chipBackGroundColor: kColorWhite,
                                chipLabelStyle: TextStyle(fontSize: 13, color: kColorLabel, fontWeight: FontWeight.w600),
                                dialogShapeBorder: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0))),
                                dialogTextStyle: kTextStyleAlertContent,
                                cancelButtonLabel: Utils.t(context, 'form.cancel').toUpperCase(),
                                onSaved: (value) {
                                  if (value == null) return;
                                  setState(() {
                                    _selectedModuleIds = value;
                                  });
                                },
                              ),
                              Positioned.fill(
                                  right: 12,
                                  bottom: _selectedModuleIds.length > 0 ? 24 : 10,
                                  child: Container(
                                    alignment: Alignment.bottomRight,
                                    child: IgnorePointer(
                                      child: Container(
                                        color: kColorBackgroundFormField,
                                        height: double.infinity,
                                        width: 25,
                                        alignment: Alignment.bottomCenter,
                                        child: Icon(
                                          Icons.arrow_drop_down_sharp,
                                          size: 25,
                                        ),
                                      ),
                                    ),
                                  ))
                            ],
                          ),
                        ),
                        SizedBox(height: 132),
                      ]))
                    ])
    

    The error message is

    E/flutter (13216): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: setState() called after dispose(): FormFieldState<dynamic>#03479(lifecycle state: defunct, not mounted)
    E/flutter (13216): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
    E/flutter (13216): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
    E/flutter (13216): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
    E/flutter (13216): #0      State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1073:9)
    E/flutter (13216): #1      State.setState (package:flutter/src/widgets/framework.dart:1108:6)
    E/flutter (13216): #2      FormFieldState.didChange (package:flutter/src/widgets/form.dart:409:5)
    E/flutter (13216): #3      new MultiSelectFormField.<anonymous closure>.<anonymous closure> (package:multiselect_formfield/multiselect_formfield.dart:120:25)
    E/flutter (13216): <asynchronous suspension>
    E/flutter (13216): 
    

    Have anyone the same problem or can help me please?

    opened by Psyphant 0
  • Initial Value is causing error.

    Initial Value is causing error.

    The method '[]' was called on null.
    Receiver: null
    Tried calling: []("display")
    

    I am using hardcoded list to test but its not working.

     MultiSelectFormField(
                              title: Text(
                                "Title Of Form",
                                style: TextStyle(fontSize: 16),
                              ),
                              dataSource: [
                                {
                                  "display": "Running",
                                  "value": "Running",
                                },
                                {
                                  "display": "Climbing",
                                  "value": "Climbing",
                                },
                              ],
                              textField: "display",
                              valueField: 'value',
                              okButtonLabel: 'OK',
                              cancelButtonLabel: 'CANCEL',
                              hintWidget: Text('Please choose one or more'),
                              initialValue: [
                                {
                                  "display": "Running",
                                  "value": "Running",
                                },
                              ],
                              onSaved: (value) {
                                if (value == null) return;
                                setState(() {
                                  // _selectedCategory = value;
                                });
                              },
                            ),
    
    opened by MuhammadAliKust 1
Owner
Carlos Eugenio Torres
Principal Software Engineer
Carlos Eugenio Torres
A Flutter widget to show a text form field to display a date or clock dialog

A Flutter widget to show a text form field to display a date or clock dialog. This widget extend TextField and has a similar behavior as TextFormField.

m3uzz Soluções em TI 82 Jan 6, 2023
RFlutter Alert is super customizable and easy-to-use alert/popup dialogs for Flutter.

RFlutter Alert is super customizable and easy-to-use alert/popup dialogs for Flutter. You may create reusable alert styles or add buttons as much as you want with ease.

Ratel 362 Jan 1, 2023
SKAlertDialog - A highly customizable, powerful and easy-to-use alert dialog for Flutter.

SKAlertDialog A highly customizable, powerful and easy-to-use alert dialog for Flutter. GIF Screenshots SKAlertDialog Basic Alert Alert with buttons A

Senthil_Kumar 7 May 18, 2022
A custom dropdown button lets the user select from a number of items

CircularDropDownMenu Description A custom dropdown button lets the user select from a number of items. The button shows the currently selected item as

Surya Dev Singh 2 Dec 5, 2020
Making-form - A form design with dart programming and auto next facility

Making-form - A form design with dart programming and auto next facility

Munem Sarker 3 Nov 15, 2022
Widget to let the user search through a keyword string typed on a customizable keyboard in a single or multiple choices list presented as a dropdown in a dialog box or a menu.

searchable_dropdown Widget to let the user search through a keyword string typed on a customizable keyboard in a single or multiple choices list prese

Bobby Stenly Irawan 108 Sep 11, 2022
Flutter widget form select a date in horizontal timeline with customizable styles.

Flutter widget form select a date in horizontal timeline with customizable styles. Getting Started You can use this package when you need to add a dat

Jose Manuel Márquez 158 Dec 2, 2022
SmartSelect allows you to easily convert your usual form select or dropdown into dynamic page

SmartSelect allows you to easily convert your usual form select or dropdown into dynamic page, popup dialog, or sliding bottom sheet with various choices input such as radio, checkbox, switch, chips, or even custom input. Supports single and multiple choice.

Irfan Vigma Taufik 332 Dec 20, 2022
A package for flutter to use alert and toast within one line code.

easy_alert A package for flutter to use alert and toast within one line code. Getting Started Add easy_alert: to your pubspec.yaml, and run flutt

null 34 Jun 25, 2021
A flutter package for the OTP Field widget.

OTP Text Field A flutter package to create a OTP Text Field widget in your application. Stay tuned for the latest updates: ?? Screenshots ⚙️ Installat

Vivek Kaushik 108 Oct 30, 2022
A Flutter GridView whose items the user can interactively reorder by dragging

A GridView whose items the user can interactively reorder by dragging. Compared to the given ReorderableListView, it is possible to reorder different

null 57 Dec 19, 2022
A Simple and easy to use flutter package for showing progress bar.

progress_dialog A Simple and easy to use flutter package for showing progress bar. #Usage Import the package import 'package:custom_progress_dialog/cu

Vikas Jilla 6 May 23, 2022
Make your native android Dialog Fancy and Gify.

Make your native android Dialog Fancy and Gify. A library that takes the standard Android Dialog to the next level with a variety of styling options and Gif's. Style your dialog from code.

Shashank Singhal 522 Jan 2, 2023
Progress Dialog widget for flutter projects with ability to customize loading widget, background color and background blur.

DISCONTINUED Checkout ArsDialog ars_progress_dialog Customizable progress dialog for Flutter applications with smooth animation for background dim col

Arsam 8 Apr 15, 2022
Dialog-manager - A Flutter package that allows for neater declaration, abstraction and use of customisable dialogs

flutter_dialog_manager A Flutter package that allows for neater declaration, abs

Lucky Ebere 2 Dec 28, 2022
Flutter progress dialog. Support both Android and iOS platform.

Flutter Progress Dialog [pub packages] | Flutter progress dialog. Support both Android and iOS platform

Dylan Wu 22 Oct 9, 2022
Display simple blurry dialog popup for flutter

Blurry Dialog Features Display simple blurry dialog popup Offer built-in themes Possibility to create you custom dialog button click handler callbacks

Kouki Badr 7 Dec 18, 2022
🚀🚀🚀 Semantic dialog

✨ flutter_custom_dialog [Language ~~] English | 中文文档 Global dialog function encapsulation, with a semantic way to fill the content inside the dialog,

YYDev 459 Dec 2, 2022
Flutter overlay loading dialog example

flutter_overlay_loading_dialog_example Demo

Javeed Ishaq 4 Mar 24, 2022