DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Drowdown Button In Flutter
Afolayan Ademola Segun
Afolayan Ademola Segun

Posted on

Drowdown Button In Flutter

Hey Guys,

Have you ever been stuck and you dont know exact thing to do anymore, trust me, there are some bugs that won't just let you kill them (if you like use BagonπŸ˜‚)...

Well I came across this bug 🐞 , yeah and I checked through Flutter documentation, Stack Overflow and the likes, couldn't get my solution.

I was able to figure it out after couple of hours and I will like to share my solution. Also I will be sharing some other solutions I came across just in case my solution doesnt fit. You can get all soluton in one stop, yah.

In this article you will be learning how to use DropDownButton and learn various properties of it in flutter and also get the solution to common bugs associated with this widget.

Lets dive in...

What is a Dropdown Button πŸ’πŸ½β€β™‚οΈ?
Dropdown Button is a Material Design button for selecting from a list of items.

DropdownButton<String>(
  value: dropdownValue,
  icon: const Icon(Icons.arrow_downward),
  elevation: 16,
  style: const TextStyle(color: Colors.deepPurple),
  underline: Container(
    height: 2,
    color: Colors.deepPurpleAccent,
  ),
  onChanged: (String? value) {
    // This is called when the user selects an item.
    setState(() {
      dropdownValue = value!;
    });
  },
  items: list.map<DropdownMenuItem<String>>((String value) 
  {
    return DropdownMenuItem<String>(
      value: value,
      child: Text(value),
    );
  }).toList(),
Enter fullscreen mode Exit fullscreen mode

The Dropdown Button has some properties and methods, To use this widget, you need to have a list of items that you will use in your dropdown. For the above example here is the list that was used

const List list = ['One', 'Two', 'Three'];

and when you run this in your flutter project, you will get something like this: πŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌ

This image shows the result of above codes

There you go!!!

Dropdown Button has a major?
You have to use this widget right, and if not, you get stuck. This is the major issue with using a Drondown Button.

Error meesage:
_Drop down Either or 2 more dropdown were detected with the same value???? _

Lets take this example as our point of focus.

  String _value1;
  String _value2;

  final List<String> nameList = <String>[
   "Name1",
    "Name2",
    "Name3",
    "Name4",
    "Name5",
    "Name6",
    "Name7",
    "Name8"
   ];

   @override
  Widget build(BuildContext context) {
    return Scaffold(
     appBar: AppBar(
     elevation: 2.0,
     title: Text('Hello'),
     ),
    body:  ListView(
        children: <Widget>[
          Row(
            children: <Widget>[
              Text('Name: '),
              Center(
                child: DropdownButton(
                  value: _value1,
                  onChanged: (value) {
                    setState(() {
                      _value1 = value;
                    });
                  },
                  items: nameList.map(
                    (item) {
                      return DropdownMenuItem(
                        value: item,
                        child: new Text(item),
                      );
                    },
                  ).toList(),
                ),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              Text('Name: '),
              Center(
                child: DropdownButton(
                  value: _value2,
                  onChanged: (value) {
                    setState(() {
                      _value2 = value;
                    });
                  },
                  items: nameList.map(
                    (item) {
                      return DropdownMenuItem(
                        value: item,
                        child: new Text(item),
                      );
                    },
                  ).toList(),
                ),
              ),
            ],
          ),
        ],
      ),
    backgroundColor: Colors.grey[200],
   );
  }
 }
Enter fullscreen mode Exit fullscreen mode

One:
Always make sure the value of the property "value" is not empty.

         DropdownButton(
          // Initial Value
          _**value: dropdownvalue,**_

          // Down Arrow Icon
          icon: const Icon(Icons.keyboard_arrow_down),   

          // Array list of items
          items: items.map((String items) {
            return DropdownMenuItem(
              value: items,
              child: Text(items),
            );
          }).toList(),
          // After selecting the desired option,it will
          // change button value to selected value
          onChanged: (String? newValue) {
            setState(() {
              dropdownvalue = newValue!;
            });
          },
        ),
Enter fullscreen mode Exit fullscreen mode

Two:
If the value is going to be promised, that is at a later time the property will get its value, then. check if the value is empty first, if it is empty replaced with a default value.

 DropdownButton(
   value: _value1.isNotEmpty ? _value1 : null, // guard it 
     with null if empty
    items: nameList.map((item) {
       return DropdownMenuItem(
          value: item,
          child: new Text(item),
        );
      }).toList(), 
    );
Enter fullscreen mode Exit fullscreen mode

Three:
If you are getting your list from the database, make sure the function you call in not in your build context, it should be called once. And the reson why that is so is because when call your api that will get the list within your build context, its get called multipble times as you are using setstate to update the selected value. Here is a complete example code ------
See here. πŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌπŸ‘‡πŸΌ

  class _ParentBankState extends 
  State<ParentCategory> {
  final _formKey = GlobalKey<FormState>();

   String? _selectedBankCategory;
    // List category = [];
   final List<String> _parentCategory = [
    "Select Category",
   ];

   _//Make sure you do your calls here_

  @override
  void initState() {
    //do your calls to get the list from your database 
   //here so that it will be called once...

  final category = context.read<AddMoneyCubit>. 
  ().loadBankList();
   super.initState();
  }

@override
 Widget build(BuildContext context) {

 //Do not call your api here, why?
 //because buildcontext get build multiple times and that 
 //will make your dropdwon throw that error, because it is 
 //seeing the value beeing used repeatedly...

  var businessBankDropDown =
    BlocBuilder<AddMoneyCubit, AddMoneyState>(
  builder: (context, state) {
    return Form(
      key: _formKey,
      child: ButtonTheme(
        alignedDropdown: true,
        child: DropdownButtonHideUnderline(
          child: DropdownButton<String>(
            menuMaxHeight: 300,
            isExpanded: true,
            value: _selectedParentCategory,
            hint: const Text(
              "Parent Category",
              style: TextStyle(fontSize: 14),
            ),
            items: state is LoadBankList
                ? state.categoryListModel.map((e) {
                    return DropdownMenuItem<String>(
                        value: e.text,
                        child: Row(
                          children: [
                            Text(
                              e.text,
                              style: const TextStyle(
                                  fontSize: 14.0, color: 
              IposColors.black),
                            ),
                          ],
                        ));
                  }).toList()
                : _parentBank.map((String value) {
                    return DropdownMenuItem<String>(
                        value: value,
                        child: Row(
                          children: [
                            Text(
                              value,
                              style: const TextStyle(
                                  fontSize: 14.0, color: 
                    IposColors.black),
                            ),
                          ],
                        ));
                  }).toList(),

            onChanged: (value) {
              setState(() {
                print(value);
           _selectedBankCategory = value;
              });
            },
            style: const TextStyle(fontSize: 30),
           ),
           ),
          ),
         );
         },
        );

    return Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height / 16.4,
       decoration: BoxDecoration(
       color: Colors.white,
       borderRadius: BorderRadius.circular(10),
       border: Border.all(
        color: Colors.grey,
       ),
     ),
     child: businessBankDropDown);
    }
  }
Enter fullscreen mode Exit fullscreen mode

This was my Solution.

Thank you for taking your time to go through this.

I hope you have learned to use this awesome widget and this helps you resolve your bugs 🐞πŸͺ² issues...

If you would like to discuss this or any related issueChat Me. Follow me on Twitter for More...

Top comments (0)

All DEV content is created by the community!

Hey, if you're landing here for the first time, you should know that this website is a global community of folks who blog about their experiences to help folks like you out.

Sign up now if you're curious. It's free!