Multi-Select Dialogue in Flutter: A Versatile Approach

Multi-Select Dialogue in Flutter

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.

So how would Mr. X solve this challenge!

Flutter has made programming not only easy but also interesting. Tons of hardcoded strings can be easily mapped using a 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 full fill the required functionality in a decent manner.

Figure 1 illustrates such a sketch.

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.

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!

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

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 ElevatedButtonOn tapping this button, the MultiSelectDialog would pop upon the screen. After submission, the selected flavours would be stored inside a List 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.

Figure 4: MultiSelectDialog Execution
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 flavours selected by the user. 
Figure 6: MultiSelect FormField Flow

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

MultiSelect Form Field 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.
  • 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.

Figure 7: Final Results
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.

https://levelup.gitconnected.com/multi-select-dialogue-in-flutter-the-unit-test-phase-1eaa291549ac

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

Leave a Reply

Your email address will not be published. Required fields are marked *