如何获取映射JSON到DropdownMenuItem的列表?

时间:2019-12-12 07:54:09

标签: flutter fetch

我在这里有一个JSON对象:

{
    "error": "0",
    "message": "Succesfully fetched",
    "data": [
        {
            "status": true,
            "_id": "5df0b94841f0331baf1357bb",
            "name": "test group",
            "description": "test description",
            "created_date": "2019-12-11T09:39:20.151Z",
            "__v": 0
        },
        {
            "status": true,
            "_id": "5df0df507091683d2f1ad0cf",
            "name": "new group",
            "created_date": "2019-12-11T12:21:36.283Z",
            "__v": 0
        }
    ]
}

我想将数据下的name参数提取到DropDownMenuList中。我在这里有一个数据模型:

class dataArray {
//  final dynamic status;
  final dynamic id;
  final dynamic groupName;

//  final dynamic description;
//  final dynamic created_date;
//  final dynamic v;


  dataArray(this.groupName, this.id);


  dataArray.fromJson(Map jsonMap)
      : groupName = jsonMap['name'],
        id = jsonMap['_id'];


  Map toMapData(){
    var mapGroup = new Map<String, dynamic>();
    mapGroup["name"] = groupName;
    mapGroup['_id'] = id;
    return mapGroup;

  }

}

要获取的功能:

Future<List<dataArray>> gettaskData() async {
  List<dataArray> list;
  String link = ""; //Cannot provide this due to confidentiality
  var res = await http
      .get(Uri.encodeFull(link), headers: {"Accept": "application/json"});
  print(res.body);
  if (res.statusCode == 200) {
    var data = json.decode(res.body);
    var rest = data["data"] as List;
    var error = data['error'];
    print("this is error = $error");
    print(rest);
    list = rest.map<dataArray>((json) => dataArray.fromJson(json)).toList();
  }
  print("List Size: ${list.length}");
  return list;
}

此方法成功将项目提取到ListView.builder小部件中,但是我对如何将其提取到List<DropdownMenuItem<T>> items有点迷惑。

我试图通过以下解决方案:

第一个链接似乎在获取列表而不是Map,第二个链接显示地图,而在我的JSON列表中,我必须显示地图列表中的值。

编辑:基于接受的答案,我还为此修改了initJson方法-

  Future initJson() async {
    _list = await loadJsonFromAsset();
//print("Printing _List = ${_list[0].groupName}");
//    if (_list.length > 0) {
    setState(() {
      for(int i =0; i<=_list.length - 1; i++) {
        _selectedMenuItem = _list[i];
      }
    });

//      }
  }

这将显示api中存在的每个对象的名称参数。

2 个答案:

答案 0 :(得分:1)

这是一个可行的解决方案,因为您不想提供您的api网址,所以我将提供的json添加到文件中并加载了它以进行详细说明:

要记住的几件事:

  • 请注意,您的命名约定不太好。我不喜欢 因此,我将dataArray重命名为DataModel(这不是很好 名称,但因为演示,确定)。
  • 如果要在获取数据时显示某些内容,可以包装 DropDownButtonFutureBuilder为默认值。
  • 您可以避免使用dynamic的{​​{1}},因为Dart可以推断数据 类型。无论如何,我总是尽可能地使用静态类型 复杂性并使我的生活变得轻松(因为这给了编译时间 错误消息)。

在我的示例中,我没有使用final。您可以参考其他答案。

FutureBuilder

关于文档中的import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:so_answers/drop_down/model.dart'; class DropDownDemo extends StatefulWidget { @override _DropDownDemoState createState() => _DropDownDemoState(); } class _DropDownDemoState extends State<DropDownDemo> { List<DataModel> _list = []; DataModel _selectedMenuItem; String selected = "hello"; Future<List<DataModel>> loadJsonFromAsset() async { String data = await DefaultAssetBundle.of(context).loadString("assets/data.json"); final decoded = json.decode(data); try { return (decoded != null) ? decoded["data"] .map<DataModel>((item) => DataModel.fromJson(item)) .toList() : []; } catch (e) { debugPrint(e.toString()); return []; } } Future initJson() async { _list = await loadJsonFromAsset(); if (_list.length > 0) { _selectedMenuItem = _list[0]; } } DropdownMenuItem<DataModel> buildDropdownMenuItem(DataModel item) { return DropdownMenuItem( value: item, // you must provide a value child: Padding( padding: const EdgeInsets.all(12.0), child: Text(item.groupName ?? ""), ), ); } Widget buildDropdownButton() { return Center( child: Padding( padding: EdgeInsets.all(20), child: DropdownButton<DataModel>( elevation: 1, hint: Text("Select one"), isExpanded: true, underline: Container( height: 2, color: Colors.black12, ), items: _list.map((item) => buildDropdownMenuItem(item)).toList(), value: _selectedMenuItem, // values should match onChanged: (DataModel item) { setState(() => _selectedMenuItem = item); }, ), ), ); } @override void initState() { initJson(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: buildDropdownButton(), ); } }

DropDownButton

有关更多信息,请参考文档:https://api.flutter.dev/flutter/material/DropdownButton-class.html

答案 1 :(得分:0)

您可以像这样进行下拉,

FutureBuilder<List<dataArray>>(
        future: gettaskData(),
        builder: (BuildContext, snapshot){
          if (snapshot.data != null) {
            //print('project snapshot data is: ${projectSnap.data}');
            return Container(
              decoration: BoxDecoration(
                  borderRadius: new BorderRadius.circular(3),
                  color: Colors.grey[300]),
              child: DropdownButtonHideUnderline(
                child: DropdownButton(
                  items: snapshot.data.map((value) {
                    return new DropdownMenuItem(
                      value: value.id,
                      child: new Text(
                        value.groupName,
                      ),
                    );
                  }).toList(),
                  value: select_dataItem == "" ? null : select_dataItem,
                  onChanged: (v) {
                    FocusScope.of(context).requestFocus(new FocusNode());
                    setState(() {
                      select_dataItem = v;
                      print("selected ${select_dataItem}");
                    });
                  },
                  isExpanded: true,
                  hint: Text(
                    'Select Source',
                  ),
                ),
              ),
            );
          }
          if(snapshot.data == null){
            return Text("No Data");
          }
          return Container();
        },
      ),