Home > Blockchain >  Drop-down menu using Map key/value pairs from api
Drop-down menu using Map key/value pairs from api

Time:07-28

How can I get data from Map and put it in dropdown menu? I have an api working on websocket which returns me a Map of objects like {"1":"cat", "2":"dog","3":"bird"}, so I wanted to create a dropdown where users can choose the animal. As I know, the Map has key/value pair, so I need to use value in my case for drop-down menu. So my code now looks like that:

body: Futurebuilder<Map>(
future: apiservice.getAnimal(), 
builder:(context, snapshot){
return: DropdownButton(
 value: snaphot.data.first,
 onChanged: (String newValue) {
     setState(() {
     snapshot.data.first = newValue; 
     });
 },
 items: snapshot.data.values.map((key, value) {
  return DropdownMenuItem(
   value: i, 
   child: Text(value));
 }).toList(),
);})

But data doesn't display or it gives the error that string can't be the Map<dynamic, dynamic>. How can I solve it?

CodePudding user response:

because the init value and the onChanged return value is a Map, You should change into into either a key or a value

Also, snapshot data is immutable and won't persisted, so you should create a list outside of the rebuild

//somewhere in your code, outside the rebuild method
String selectedAnimal = "";
var map = [];

body: Futurebuilder<Map<String,String>>(
future: apiservice.getAnimal(), 
builder:(context, snapshot){
map = snapshot.data;
return: DropdownButton(
 value: selectedAnimal ?? map.keys.first,
 onChanged: (String newValue) {
     setState(() {
     selectedAnimal = map[newValue]; 
     });
 },
 items: map.map((key, value) {
  return DropdownMenuItem(
   value: key, 
   child: Text(value));
 }).toList(),
);})

CodePudding user response:

It better to create future outside the build method, like on state class or on initState.

late  final _apiService = apiservice.getAnimal();

String? selected;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: FutureBuilder<Map<String, String>>(
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          final Map<String, String> data = snapshot.data!;
          return DropdownButton<String?>(
            items: data.keys
                .toList()
                .map(
                  (e) => DropdownMenuItem<String>(
                    child: Text(
                      data[e] ?? "",
                    ),
                    value: data[e],
                  ),
                )
                .toList(),
            onChanged: (v) {
              setState(() {
                selected = v;
              });
            },
          );
        }
        return CircularProgressIndicator();
      },
    ),
  );
}
  • Related