Flutter Multi-select ChoiceChip

Karthik Ponnam
4 min readApr 17, 2019

--

Hello Everyone

In this article, we will see how to use ChoiceChip to accept multiple selections

Let’s get started

First things first

I will create a demo project and in the main.dart in build sections, I will create a RaisedButton so whefirstn I click on the button a dialog will be popped showing options to select.

Center(
child: RaisedButton(
child: Text("Report"),
onPressed: () {
//Here we call the open dialog
},
),
),

Now onPressed we need to call the Open Dialog

class _MyHomePageState extends State<MyHomePage> {
// This function will open the dialog
_showReportDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
//Here we will build the content of the dialog
}
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: RaisedButton(
child: Text("Report"),
onPressed: () => _showReportDialog(),
),
),
);
}
}

Now I will create a Widget to hold and return the ChoiceChip

Here is the widget which accepts a List<String> so I can populate the Chips using it

Now our widget has a single Choice “Not Interested”

class MultiSelectChip extends StatefulWidget {
final List<String> reportList;
MultiSelectChip(this.reportList); @override
_MultiSelectChipState createState() => _MultiSelectChipState();
}
class _MultiSelectChipState extends State<MultiSelectChip> {
bool isSelected = false;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(8.0),
child: ChoiceChip(
label: Text("Not Interested"),
selected: isSelected,
onSelected: (selected) {
setState(() {
isSelected = selected;
});
},
),
);
}
}
ChoiceChip Demo

Now in _showReportDialog function we need to call Our widget.

List<String> reportList = [
"Not relevant",
"Illegal",
"Spam",
"Offensive",
"Uncivil"
];
_showReportDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
//Here we will build the content of the dialog
return AlertDialog(
title: Text("Report Video"),
content: MultiSelectChip(reportList),
actions: <Widget>[
FlatButton(
child: Text("Report"),
onPressed: () => Navigator.of(context).pop(),
)
],
);
});
}
}

Now let's populate the chips based on the reportList Now our Widget will become this one

class MultiSelectChip extends StatefulWidget {
final List<String> reportList;
MultiSelectChip(this.reportList); @override
_MultiSelectChipState createState() => _MultiSelectChipState();
}
class _MultiSelectChipState extends State<MultiSelectChip> {
String selectedChoice = "";
// this function will build and return the choice list
_buildChoiceList() {
List<Widget> choices = List();
widget.reportList.forEach((item) {
choices.add(Container(
padding: const EdgeInsets.all(2.0),
child: ChoiceChip(
label: Text(item),
selected: selectedChoice == item,
onSelected: (selected) {
setState(() {
selectedChoice = item;
});
},
),
));
});
return choices;
}
@override
Widget build(BuildContext context) {
return Wrap(
children: _buildChoiceList(),
);
}
}

Now we have a single select chip in order to make it multi-select chip we need to save out selectedChoice to a list, let's work it out.

Now to achieve this we use some methods available with the List

selectedChoices.contains(item) selectedChoices.remove(item) selectedChoices.add(item)

Now our _buildChoiceList will look like below

// String selectedChoice = "";
List<String> selectedChoices = List();
_buildChoiceList() {
List<Widget> choices = List();
widget.reportList.forEach((item) {
choices.add(Container(
padding: const EdgeInsets.all(2.0),
child: ChoiceChip(
label: Text(item),
selected: selectedChoices.contains(item),
onSelected: (selected) {
setState(() {
selectedChoices.contains(item)
? selectedChoices.remove(item)
: selectedChoices.add(item);
});
},
),
));
});
return choices;
}

The login we used here is if the list contains the item then we make it selected else unselected in the same way then a chip is selected if the List already contains the item then we remove the existing one else we add the item into the List

selected: selectedChoices.contains(item),

and

setState(() {
selectedChoices.contains(item)
? selectedChoices.remove(item)
: selectedChoices.add(item);
});

Now the part is to pass the selected choices back we can achive this by passing a function which accepts a List<String> in to our Widget this how our code will be

In the content of our AlertDialog in _showReportDialog

MultiSelectChip(
reportList,
onSelectionChanged: (selectedList) {
setState(() {
selectedReportList = selectedList;
});
},
),

Our MultiSelectChip Will be like below

class MultiSelectChip extends StatefulWidget {
final List<String> reportList;
final Function(List<String>) onSelectionChanged; // +added
MultiSelectChip(
this.reportList,
{this.onSelectionChanged} // +added
);
@override
_MultiSelectChipState createState() => _MultiSelectChipState();
}
class _MultiSelectChipState extends State<MultiSelectChip> {
// String selectedChoice = "";
List<String> selectedChoices = List();
_buildChoiceList() {
List<Widget> choices = List();
widget.reportList.forEach((item) {
choices.add(Container(
padding: const EdgeInsets.all(2.0),
child: ChoiceChip(
label: Text(item),
selected: selectedChoices.contains(item),
onSelected: (selected) {
setState(() {
selectedChoices.contains(item)
? selectedChoices.remove(item)
: selectedChoices.add(item);
widget.onSelectionChanged(selectedChoices); // +added
});
},
),
));
});
return choices;
}
@override
Widget build(BuildContext context) {
return Wrap(
children: _buildChoiceList(),
);
}
}

Whenever our selection of chip changed we will trigger the onSelectionChanged

Our HomePageState build method will be as below

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("Report"),
onPressed: () => _showReportDialog(),
),
Text(selectedReportList.join(" , ")),
],
),
),
);
}

So this is how can make a multi-select choice chip

To get all options available with ChoiceChip check here

To get Full Source code check out my GitHub repo

Bonus

If you want to add the option to limit the number of selections refer the below gist code to get the code

Thanks for your time.

Hope you like it, if yes clap & share.

--

--

Karthik Ponnam
Karthik Ponnam

Written by Karthik Ponnam

❤️ to Code. Full Stack Developer, Flutter, Android Developer, Web Development, Known Languages Java, Python so on.,

Responses (5)