Making a dropdown menu in Flutter with a Map

Viewed 16850

so i'm wanting to create an object in flutter that takes a Map<String, int> as a list of values, where the String is what is displayed in the menu, and the int is stored inside the class for later usage after an item is selected.

i am unsure how to do this. the part involving returning the int value eludes me.

the map structure is written like this:

  final Map<String, int> discBasis = {
    'Age': 1,
    'Ancestry': 2,
    'Color': 3,
    'Disability': 4,
    'Race': 5,
    'Religion': 6,
    'Sex': 7,
    'Familial Status': 8,
    'National Origin': 9
  };

& the class which i am currently using:

final double formMarginHoriz = 10.0;
final double formMarginVert = 5.0;

class DropDownFromMap extends StatefulWidget {
  Map<String, int> kv;
  DropDownFromMap(this.kv);

  @override
  DropDownFromMapState createState() => new DropDownFromMapState(kv);
}

class DropDownFromMapState extends State<DropDownFromMap> {
  Map<String, int> kv;
  DropDownFromMapState(this.kv);

  int selectedVal;

  @override
  Widget build(BuildContext context) {
    return new Container(
        margin: EdgeInsets.only(
            top: formMarginVert,
            bottom: formMarginVert,
            left: formMarginVert,
            right: formMarginHoriz),
        child: new DropdownButton<int>(
          hint: new Text("Select an option"),
          value: selectedVal,
          onChanged: (String newVal) {
            setState(() {
              selectedVal = kv[newVal];
            });
          },
          items: kv.map((String k, _) {
            return new DropdownMenuItem<String>(
              value: k,
              child: new Text(k),
            );
          }).toList(),
        ));
  }
}

and it is instantiated like this (this is probably wrong):

  @override
  Widget build(BuildContext context) {
    return new Material(
        color: Colors.blueAccent,
        child: new Container(
            child: new Form(
                key: _formKey,
                child: new Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    new DropDownFromMap(data.offenderType),
...

more context can be found at the github project: https://github.com/chscodeforchange/icrc-app in the relevant files: dropdown.dart, off_page_one.dart, & form_data.dart.

thank you in advance!

3 Answers
static const Map<String, Duration> frequencyOptions = {
    "30 seconds": Duration(seconds: 30),
    "1 minute": Duration(minutes: 1),
    "2 minutes": Duration(minutes: 2),
  };

Duration _frequencyValue = Duration(seconds: 30);

@override
  Widget build(BuildContext context) {
    return DropdownButton<Duration>(
          items: frequencyOptions
              .map((description, value) {
                return MapEntry(
                    description,
                    DropdownMenuItem<Duration>(
                      value: value,
                      child: Text(description),
                    ));
              })
              .values
              .toList(),
          value: _frequencyValue,
          onChanged: (Duration? newValue) {
            if (newValue != null) {
              setState(() {
                _frequencyValue = newValue;
              });
            }
          },
        );
}

Instead of using Map use this,

final List<DropdownMenuItem> list = [
DropdownMenuItem(value: "", child: Container((...your widget style), child: Text("Select"))),
DropdownMenuItem(value: "value1", child: Container((...your widget style), child: Text("title1"))),
DropdownMenuItem(value: "value2", child: Container((...your widget style), child: Text("title2")))
];

DropdownButton(
              value: "",
              items: list,
              onChanged: (value) {},
            ),

with this you could use your own variations. I thought this was the best way for me as I had to hard code just two or three items to show up in the dropdown. You can create a seperate Model and use this idea to generate any type of dropdown list with map.

I do not see anything wrong with your code except is that you need to remove the constructor and the map in the State object, and only leave the ones inside the StatefulWidget itself. You can access your map then by using widget.kv

Related