1
votes

Hey Guys i am facing a problem i am retrieving data from an api with this code

class carLists{

carLists();
getCarsFromNetwork(String jsonUrl) async {
List<Cars> list;
String link = jsonUrl;
var res = await http.get(Uri.encodeFull(link),headers: {"Accept":"Application/json"});
if (res.statusCode == 200) {
var data = json.decode(res.body);
var list = data["cars"] as List;
List<Cars> imagesList = list.map((i) => Cars.fromJson(i)).toList();

return imagesList;
}
}
List<DropdownMenuItem> getCars(List<Cars> carPlates){
List<DropdownMenuItem<String>> ordersType = new List<DropdownMenuItem<String>>();

for(var i = 0 ; i<carPlates.length;i++ ) {


    ordersType.add(DropdownMenuItem(
      value: carPlates[i].carPlate, child: Text(carPlates[i].carPlate),));

}
return ordersType;
}

}

And implementing a dropdownbutton using these two functions to get the data and return the dropdownmenuitem list :`

Future<List<Cars>> foo(String link) async{

carPlates =  await carLists().getCarsFromNetwork(link);
print(carPlates.length);
return carPlates;
}

getItems(List values) {
List<DropdownMenuItem<String>> ordersType = new List<
    DropdownMenuItem<String>>();
for (var i = 0; i > values.length; i++) {
  ordersType.add(DropdownMenuItem(value: values[i], child: values[i],));

  return ordersType;
}
}

`and using this code to populate the DropdownButton

Container(

    child: FutureBuilder(
        future: foo(url) ,
        builder: (context, snapshot){
     if(snapshot.hasData)
       {
         return new DropdownButton(
           iconDisabledColor: Colors.black,
           isExpanded: true,
           icon: Icon(FontAwesomeIcons.arrowCircleDown),
           iconSize: 14,
           style: TextStyle(fontSize: 16, color: Colors.black),
           iconEnabledColor: Colors.deepOrange,
           items: carLists().getCars(carPlates),
           value: dropTyreBrand,
           onChanged: (val) {
             setState(() {
               dropTyreBrand = val;

             });
           },
         );
       }else{

          return CircularProgressIndicator();

     }
        }
    ),
  ) ,

the values are populated and everything is fine but when i select a value from the dropdown it crashes with this error

I/flutter ( 4578): The following assertion was thrown building FutureBuilder>(dirty, state: I/flutter ( 4578): _FutureBuilderState>#f394d): I/flutter ( 4578): 'package:flutter/src/material/dropdown.dart': Failed assertion: line 608 pos 15: 'items == null || I/flutter ( 4578): items.isEmpty || value == null || items.where((DropdownMenuItem item) => item.value == I/flutter ( 4578): value).length == 1': is not true. I/flutter ( 4578): I/flutter ( 4578): Either the assertion indicates an error in the framework itself, or we should provide substantially I/flutter ( 4578): more information in this error message to help you determine and fix the underlying cause. I/flutter ( 4578): In either case, please report this assertion by filing a bug on GitHub: I/flutter ( 4578): https://github.com/flutter/flutter/issues/new?template=BUG.md I/flutter ( 4578): I/flutter ( 4578): When the exception was thrown, this was the stack: I/flutter ( 4578): #2 new DropdownButton

1

1 Answers

2
votes

If you use FutureBuilder and in items you need to use snapshot.data
That's why error say items == null or items is empty

demo code snippet

return DropdownButton<Designations>(
                    items: snapshot.data
                        .map((designation) => DropdownMenuItem<Designations>(
                              child: Text(designation.designation),
                              value: designation,
                            ))
                        .toList(),

demo full code

import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;

void main() => runApp(MyApp());

// To parse this JSON data, do
//
//     final designations = designationsFromJson(jsonString);

List<Designations> designationsFromJson(String str) => List<Designations>.from(
    json.decode(str).map((x) => Designations.fromJson(x)));

String designationsToJson(List<Designations> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Designations {
  String designationId;
  String designation;

  Designations({
    this.designationId,
    this.designation,
  });

  factory Designations.fromJson(Map<String, dynamic> json) => Designations(
        designationId: json["DesignationId"],
        designation: json["Designation"],
      );

  Map<String, dynamic> toJson() => {
        "DesignationId": designationId,
        "Designation": designation,
      };
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: JsonApiDropdown(),
    );
  }
}

class JsonApiDropdown extends StatefulWidget {
  @override
  JsonApiDropdownState createState() {
    return new JsonApiDropdownState();
  }
}

class JsonApiDropdownState extends State<JsonApiDropdown> {
  Designations _currentDesignation;

  final String uri = 'https://jsonplaceholder.typicode.com/users';

  Future<List<Designations>> _fetchDesignation() async {
    String jsonString =
        '[ { "DesignationId": "CDG0008", "Designation": "Avp - Associate Vice President" }, { "DesignationId": "CDG0004", "Designation": "Ceo - Chief Executive Officer" } ]';
    final designations = designationsFromJson(jsonString);
    return designations;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Fetching data from JSON - DropdownButton'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            FutureBuilder<List<Designations>>(
                future: _fetchDesignation(),
                builder: (BuildContext context,
                    AsyncSnapshot<List<Designations>> snapshot) {
                  if (!snapshot.hasData) return CircularProgressIndicator();
                  return DropdownButton<Designations>(
                    items: snapshot.data
                        .map((designation) => DropdownMenuItem<Designations>(
                              child: Text(designation.designation),
                              value: designation,
                            ))
                        .toList(),
                    onChanged: (Designations value) {
                      setState(() {
                        _currentDesignation = value;
                      });
                    },
                    isExpanded: false,
                    //value: _currentUser,
                    hint: Text('Select User'),
                  );
                }),
            SizedBox(height: 20.0),
            _currentDesignation != null
                ? Text("designation: " +
                    _currentDesignation.designation +
                    "\n id: " +
                    _currentDesignation.designationId)
                : Text("No selected"),
          ],
        ),
      ),
    );
  }
}

enter image description here