multi_select_flutter 1.0.5

  • Readme
  • Changelog
  • Example
  • Installing
  • new66

Multi Select Flutter #

Multi Select Flutter is a package for easily creating multi-select widgets in a variety of ways.

drawing           drawing

Features #

  • Can use MultiSelectFormField for use with validators and other FormField methods.
  • Neutral default design that can be altered to your heart's content.
  • Easily switch the MultiSelectField's dialogType from LIST to CHIP.
  • Make your multi select searchable for large lists.
  • Separate widget for MultiSelectChipDisplay that has the ability to delete from the selected items list when a chip item is tapped.
  • Separate widgets for MultiSelectListDialog / MultiSelectChipDialog that you can simply use in the builder of showDialog(), and can be triggered with your own button.

Install #

Add this to your pubspec.yaml file:

dependencies:
  multi_select_flutter: ^1.0.5

Usage #

MultiSelectListDialog / MultiSelectChipDialog

These widgets can be used in the builder of showDialog().

  void _showMultiSelectDialog(BuildContext context) async {
    _selectedItems = await showDialog(
      context: context,
      builder: (ctx) {
        return MultiSelectListDialog(
          items: _items.map((item) => 
            MultiSelectItem(item, item.name)).toList(),
          title: "Dialog Title",
          initialSelectedItems: _selectedItems,
        );
      },
    );
  }

MultiSelectChipDisplay

This widget can be used by itself, alongside one of the dialogs, or it can be specified as a parameter of MultiSelectField / MultiSelectFormField.

To use this widget effectively, make sure to set the state when the list of items is changed.

You can also remove items from the source list in the onTap function.


MultiSelectChipDisplay(
  items: _selectedItems.map((item) => 
    MultiSelectItem(item, item.name)).toList(),
  onTap: (item) {
    setState(() {
      _selectedItems.remove(item);
    });
  },
),

MultiSelectField

MultiSelectField provides a button which opens the dialog. To save the values from the dialog using this widget, an onConfirm(values) function is provided.

MultiSelectField(
  title: "Animals",
  buttonText: "Favorite Animals"
  items: items.map((e) => MultiSelectItem(e, e)).toList(),
  dialogType: MultiSelectDialogType.CHIP,
  searchable: true,
  decoration: BoxDecoration(
    color: Theme.of(context).primaryColor.withOpacity(.4),
    border: Border.all(color: Theme.of(context).primaryColor),
  ),
  textStyle: TextStyle(fontSize: 20),
  onConfirm: (results) {
    setState(() {
      _selectedAnimals = results;
    });
  },
  chipDisplay: MultiSelectChipDisplay(
    items: _selectedAnimals != null 
      ? _selectedAnimals.map((e) => MultiSelectItem(e, e)).toList() 
      : [],
  ),
),

MultiSelectFormField

MultiSelectFormField is the FormField version of MultiSelectField. You can put it into a form and make use of FormField parameters such as validator and onSaved.

It also comes with a default bottom-border that can be overriden with the decoration parameter.

Form(
  child: MultiSelectFormField(
    key: _formFieldKey,
    buttonIcon: Icon(Icons.arrow_forward_ios),
    validator: (value) {
      if (value == null || value.isEmpty) {
        return "Required";
      }
      return null;
    },
    title: "Animals",
    items: items,
    onConfirm: (values) {
      _selectedAnimalItems = values;
      _formFieldKey.currentState.validate();
    },
    chipDisplay: MultiSelectChipDisplay(
      items: _selectedAnimals != null 
        ? _selectedAnimals.map((e) => MultiSelectItem(e, e)).toList() 
        : [],
    ),
  ),
),

Contributing #

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Changelog #

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased] #

  • Multi select bottom sheet widget.

[1.0.5] - 2020-07-10 #

Fixed #

  • A bug was introduced in version 1.0.4 that caused the MultiSelectFormField to not highlight any of the selected values in the dialog.

Added #

  • Boolean parameter 'searchable'. Useful for larger lists, the searchable parameter enables a search icon in the dialog which shows a search bar that lets you query the list.

Added #

  • String parameters for 'confirmText' and 'cancelText'. This is important for users who want text other than 'OK' and 'CANCEL', especially for other languages and alphabets.

[1.0.4] - 2020-07-06 #

Changed #

  • Allow user to set initial selected values for MultiSelectField and MultiSelectFormField by adding param 'initialValue' to MultiSelectField, and enabled the same functionality for MultiSelectFormField by passing its existing 'initialValue' param to the MultiSelectField's new 'initialValue' param.
    • MultiSelectFormField creates a MultiSelectField which never had an 'initialValue' param that could be set by the user. Even if 'initialValue' was set on the MultiSelectFormField, it never got passed to the MultiSelectField that it creates. Now it does.
    • Previously when using a MultiSelectField or FormField, the values in the MultiSelectListDialog / MultiSelectChipDialog were only being stored internally when a user confirms the values. Now the initial values can be set before any user interaction has occurred.
    • Another use case is when a MultiSelectField is being re-inserted into the widget tree (such as one inside of a PersistentBottomSheet), and if the developer wants the previously selected values to remain after the bottomsheet re-opens, they can use this parameter to achieve that.
  • Updated example app
  • Updated readme
  • Added unreleased section to changelog

[1.0.3] - 2020-06-21 #

Changed #

  • Updated pubspec.yaml project description and added homepage link

[1.0.2] - 2020-06-20 #

Added #

  • Example project
  • analysis_options.yaml

[1.0.1] - 2020-06-20 #

Changed #

  • Updated readme

[1.0.0] - 2020-06-20 #

Added #

  • Creation of MultiSelect package
  • Widgets include with MultiSelectListDialog, MultiSelectChipDialog, MultiSelectChipDisplay, MultiSelectField, MultiSelectFormField.

example/lib/main.dart

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Multi Select',
      theme: ThemeData(
        primarySwatch: Colors.purple,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Multi Select'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static List<String> _animals = [
    "Cat",
    "Rabbit",
    "Fish",
    "Mouse",
    "Dog",
    "Zebra",
    "Cow",
    "Frog",
    "Blue Jay"
  ];
  final items = _animals
      .map((animal) => MultiSelectItem<String>(animal, animal))
      .toList();
  List<String> _selectedAnimals;
  List<String> _selectedAnimals2;
  List<String> _selectedAnimals4;
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Container(
          alignment: Alignment.center,
          padding: EdgeInsets.all(20),
          child: Column(
            children: <Widget>[
              SizedBox(height: 40),
              Container(
                width: 300,
                //################################################################################################
                // MultiSelectField
                //################################################################################################
                child: MultiSelectField(
                  decoration: BoxDecoration(
                    color: Colors.blue.withOpacity(0.1),
                    borderRadius: BorderRadius.all(Radius.circular(40)),
                    border: Border.all(
                      color: Colors.blue,
                      width: 2,
                    ),
                  ),
                  buttonIcon: Icon(
                    Icons.pets,
                    color: Colors.blue,
                  ),
                  buttonText: "Favorite Animals",
                  title: "Animals",
                  items: items,
                  onConfirm: (results) {
                    setState(() {
                      _selectedAnimals = results;
                    });
                  },
                  textStyle: TextStyle(fontSize: 20, color: Colors.blue),
                  chipDisplay: MultiSelectChipDisplay(
                    chipColor: Colors.lightBlue[100],
                    textStyle: TextStyle(color: Colors.blue),
                    items: _selectedAnimals != null
                        ? _selectedAnimals
                            .map((e) => MultiSelectItem<String>(e, e))
                            .toList()
                        : [],
                    onTap: (value) {
                      setState(() {
                        _selectedAnimals.remove(value);
                      });
                    },
                  ),
                ),
              ),
              SizedBox(height: 50),
              //################################################################################################
              // This MultiSelectField has no decoration, but is instead wrapped in a container that has
              // decoration applied. This allows the ChipDisplay to render inside the same container.
              //################################################################################################
              Container(
                decoration: BoxDecoration(
                  color: Theme.of(context).primaryColor.withOpacity(.4),
                  border: Border.all(
                    color: Theme.of(context).primaryColor,
                    width: 2,
                  ),
                ),
                width: 300,
                child: Column(
                  children: <Widget>[
                    MultiSelectField(
                      dialogType: MultiSelectDialogType.CHIP,
                      buttonText: "Favorite Animals",
                      title: "Animals",
                      items: items,
                      onConfirm: (results) {
                        setState(() {
                          _selectedAnimals2 = results;
                        });
                      },
                      textStyle: TextStyle(fontSize: 20),
                      chipDisplay: MultiSelectChipDisplay<String>(
                        items: _selectedAnimals2 != null
                            ? _selectedAnimals2
                                .map((e) => MultiSelectItem<String>(e, e))
                                .toList()
                            : [],
                        onTap: (value) {
                          setState(() {
                            _selectedAnimals2.remove(value);
                          });
                        },
                      ),
                    ),
                    _selectedAnimals2 == null || _selectedAnimals2.isEmpty
                        ? Container(
                            padding: EdgeInsets.all(10),
                            alignment: Alignment.centerLeft,
                            child: Text(
                              "None selected",
                              style: TextStyle(color: Colors.black54),
                            ))
                        : Container(),
                  ],
                ),
              ),
              SizedBox(height: 40),
              //################################################################################################
              // MultiSelectFormField with validators
              //################################################################################################
              Form(
                key: _formKey,
                child: MultiSelectFormField(
                  buttonIcon: Icon(
                    Icons.arrow_drop_down,
                    size: 30,
                  ),
                  validator: (value) {
                    if (value == null || value.isEmpty) {
                      return "Required";
                    }
                    if (value.contains("Frog")) {
                      return "Frogs are weird!";
                    }
                    return null;
                  },
                  onSaved: (value) {
                    _selectedAnimals4 = value;
                  },
                  title: "Animals",
                  items: items,
                  dialogType: MultiSelectDialogType.CHIP,
                  onConfirm: (values) {
                    _formKey.currentState.validate();
                    setState(() {
                      _selectedAnimals4 = values;
                    });
                  },
                  buttonText: "Favorite Animals",
                  chipDisplay: MultiSelectChipDisplay(
                    onTap: (item) {
                      setState(() {
                        _selectedAnimals4.remove(item);
                        _formKey.currentState.validate();
                      });
                    },
                    items: _selectedAnimals4 != null
                        ? _selectedAnimals4
                            .map((e) => MultiSelectItem(e, e))
                            .toList()
                        : [],
                  ),
                ),
              ),
              SizedBox(height: 40),
              RaisedButton(
                child: Text("Submit"),
                onPressed: () {
                  _formKey.currentState.validate();
                },
              )
            ],
          ),
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  multi_select_flutter: ^1.0.5

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:multi_select_flutter/multi_select_flutter.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
32
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
66
Learn more about scoring.

We analyzed this package on Jul 11, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

Because:

  • multi_select_flutter that is a package requiring null.

Health suggestions

Format lib/multi_select_flutter.dart.

Run flutter format to format lib/multi_select_flutter.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8 1.2.2
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
Dev dependencies
flutter_test