Multi-Select Dialogue in Flutter: A Versatile Approach

Zujaj Misbah Khan
Level Up Coding
Published in
5 min readMar 2, 2021

--

A header image displaying Multi-Select Dialog

Imagine a person, Mr. X, hired as a newbie flutter developer in the Research & Development department of an ordinary biscuit manufacturing agency. Eventually, the sales trend started to drop off on weekly basis.

To resolve this issue, the Head of Department held a meeting and decided to create a questionnaire in their existing app. The Project Manager distributed various tasks to the development team and assigned Mr. X with only a short time to write code along with the restriction to use any third-party libraries such as Pubspec Packages¹.

The job was to create a button that would pop a simple dialogue box allowing a user to select multiple options and hit submit.

Rubik’s Cube — Used to Present A Challenge Context
Photo by Olav Ahrens Røtne on Unsplash

So how would Mr. X solve this challenge!

FLUTTER TO THE RESCUE

Flutter has made programming not only easy but also interesting. Tons of hardcoded string can be easily mapped using few lines of dart code, one can overcome the defects of manual event handling. Using the declarative UI approach, flutter helps to write code efficiently within a few minutes.

After some brainstorming, Mr. X sketched a basic design that would fulfill the required functionality in a decent manner . Below figure 1 illustrates such a sketch.

A basic sketch that describes a button poping up a question dialogue with multiple options and a submit button
Figure 1 : A Basic User Interface Sketch

Upon observing the sketch, he concluded that the following widgets would be used throughout the scenario as shown in Figure 2.

A sketch showing UI components broken into flutter widgets.
Figure 2 : UI components broken into widgets
  • A custom Demo Page as the main page.
  • An Elevated Button² to pop up the dialogue.
  • A Simple Dialog³ that shows a question and list of options.
  • A list of CheckboxListTile⁴ that wraps the option text in the title property & option selected in the value property.
  • An Elevated Button wrapped in an Align⁵ widget for submission.

READY, STEADY CODE!

Image displays matrix code
Photo by Markus Spiske on Unsplash

Mr. X used the concept of “Divide & Conquer” and started off by creating pages and widgets folder inside the lib folder.

The Coding Structure
Figure 3: The Coding Structure

Inside the widgets folder, he created a custom dialog as a Stateless Widget.

MultiSelectDialog Widget Code
  • To handle extensive text formatting, Mr. X declared the question as a widget instead of a simple string.
  • To display the options, he created a variable answers that would hold the hardcoded text as a list of strings.
  • To track the selected answers, he transformed the list into a Map<String, bool> mappedItem by creating a function called initMap that would return a map using dart’s Map.fromIterable⁶ constructor.
  • Inside the build method, he created a SimpleDialog having question as its title and a list of CheckboxListTile that were wrapped inside a StatefulBuilder using the mappedItem keys.
  • To check or uncheck the box, setState was used in the OnChanged callback function.
  • Upon pressing the ElevatedButton, only items having true value would be returned by the dialog.
Demo Page Code

Inside the pages folder, Mr. X created a demo page that would simply show an ElevatedButton. On tapping this button, the MultiSelectDialog would pop upon the screen. After submission, the selected flavours would be stored inside a List<String> flavors. To execute the code, he invoked the demopage in the main.dart file.

main.dart

The final results can be illustrated below in figure 4 and 5.

Gif shows the final outcome after successful code execution
Figure 4: MultiSelectDialog Execution
The Debug Console shows the selected flavors
Figure 5: Debug Console Log

IS IT OVER? NOT YET!

Although the basic functionality was completed but Mr. X noticed some enhancements that could resolve the following issues:

  1. A user can close the dialogue without making a selection at any instance.
  2. A validator is required to show error if the user makes no selection.
  3. The Flavours button should be replaced with a Form widget.
  4. Currently there’s no way to show number of flavors selected by the user.
An updated sketch that displays the flow of multiselect form field.
Figure 6: MultiSelect FormField Flow

To tackle these problems, Mr. X wrapped the MultiSelectDialog inside a custom form field in the widgets folder.

MultiSelectFormField Code
  • To create a custom form field, Mr. X extended the FormField class which is default provided by flutter.
  • The base constructor is invoked using the super keyword to get the form field’s properties and call back functions.
  • The onSaved & validator are the two stepping stones that would trigger based upon the form’s current state.
  • The ElevatedButton was replaced with a custom elevated Card Container to make the button look larger and appealing.
  • Multiple conditions were defined depending upon the form field’s state value like:
    ★ How to avoid null state?
    ★ How many flavors were selected by the user?
    ★ How to change the buttonText as per flavors selected?
  • Instead of directly taking up the question and answers, now these would be forwarded to the MultipleSelectDialog through the MultiSelectFormField’s constructor.
  • In case of validation failure, error handling became smooth using the form field’s state.hasError property.
Updated Demo Page Code
  • To integrate the changes with the demo page, Mr. X modified the basic code by replacing the ElevatedButton with a Form.
  • A GlobalKey ⁸<FormState> was used to keep track of the form’s state.
  • In the validator callback function, it was checked that at least one flavor should be selected by the user.
  • The onSaved method would trigger only if the field is valid.

THE END

After executing the main.dart file, all goals were achieved successfully as shown in figure 7 and 8.

The final updated working dialog
Figure 7: Final Results
The Updated Debug Console Log
Figure 8: Debug Console Log

Luckily, Mr. X has placed the full source code available here⁹.

Note: If you’re interested to test this app, follow the below link.

REFERENCES

[1]: Dart Packages
https://pub.dev/

[2]: Elevated Button Class
https://api.flutter.dev/flutter/material/ElevatedButton-class.html

[3]: Simple Dialog Class
https://api.flutter.dev/flutter/material/SimpleDialog-class.html

[4]: CheckboxListTile Class
https://api.flutter.dev/flutter/material/CheckboxListTile-class.html

[5]: Align Class
https://api.flutter.dev/flutter/widgets/Align-class.html

[6]: Map<K, V>.fromIterable Constructor
https://api.dart.dev/stable/2.10.5/dart-core/Map/Map.fromIterable.html

[7]: FormField<T> Class
https://api.flutter.dev/flutter/widgets/FormField-class.html

[8]:GlobalKey Class
https://api.flutter.dev/flutter/widgets/GlobalKey-class.html

[9]:Full Source Code
https://github.com/Zujaj/multiple_selection_dialogue_app

--

--

A passionate flutter developer who loves to learn, explore and share knowledge. Serving at https://telicsolutions.com/