无法使用抖动中的对象预先填充下拉菜单 [英] Not able to prepopulate dropdown with object in flutter

查看:108
本文介绍了无法使用抖动中的对象预先填充下拉菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个下拉列表,其中填充了从API接收的对象.问题是当用户进行编辑时,我无法使用对象预填充下拉列表.

I've a dropdown which is populated with objects received from API. The problem is I'm not able to pre-populate the dropdown with the object when the user takes edit.

这是示例JSON:

[{"_id":"435463","userId":"3423423","username":"ma","categoryId":"5656756","insurerId":"567544","packageId":"5675","categoryName":"vehicle insurance","insurerName":"lic","packageName":"family"},      {"_id":"4564644","userId":"2342344","username":"ma","categoryId":"6575744","insurerId":"567567","packageId":"3455","categoryName":"life insurance","insurerName":"lic","packageName":"family"}]
``


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

    UserPackages selectedPckg;
    class AddOrEditClaim extends StatefulWidget {
      @override
      AddOrEditClaimState createState() => AddOrEditClaimState();
    }

    class AddOrEditClaimState extends State<AddOrEditClaim> {
      List<UserPackages> packageList = List();
      final formKey = GlobalKey<FormState>();

      @override
      void initState() {
            fetchPackages();
            selectedPckg= UserPackages();
            UserPackages packgToEdit = new UserPackages();
            packgToEdit.packageId="123";
            packgToEdit.packageName="family";
            selectedPckg=packgToEdit;

             super.initState();
      }

      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return new Scaffold(
            appBar: AppBar(
              title: Text('Add Claim'),
            ),
            body:
                Form(
                  key:formKey,
                  child:ListView(
                      children: <Widget>[
                        new DropdownButton(
                          items: packageList.map((item) {
                            return new DropdownMenuItem<UserPackages>(
                              child: new Text(item.packageName),
                              value: item,
                            );
                          }).toList(),
                          onChanged: (newVal) {
                            setState(() {
                              selectedPckg = newVal;
                            });
                          },
                          value: selectedPckg,
                        ),
                      ])
                )

        );;
      }
       fetchPackages() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        var resp = await http.get('http://www.mocky.io/v2/5da94ca131000058004e0769');
        setState(() {
          packageList= parsePackages(resp.body);
        });
      }

      List<UserPackages> parsePackages(String responseBody) {
        final parsedj = json.decode(responseBody);
        final parsed = parsedj.cast<Map<String, dynamic>>();
        return parsed.map<UserPackages>((json) => UserPackages.fromJson(json)).toList();
      }
    }


Here is the Userpackages class:


    class UserPackages{
       String packageName;
       String packageId;
      UserPackages({this.packageName,this.packageId});
      factory UserPackages.fromJson(Map<String, dynamic> json){
        return UserPackages(
          packageId:json['packageId'] as String,
          packageName: json['packageName'] as String,
        );
      }
    }


The following is being thrown


    'package:flutter/src/material/dropdown.dart': Failed assertion: line 560 pos 15: 'items == null ||items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value ==value).length == 1': is not true.


推荐答案

截屏:

代码:

您的代码中有太多错误,我只是创建了一个最小的可复制代码,向您显示了您想要实现的目标.如果您不想创建本地虚拟DropdownMenuItem,则应使用FutureBuilder,为简单起见,我创建了它.

There were too many mistakes in your code, I just created a minimal reproducible code showing you what you want to achieve. You should use FutureBuilder if you don't want to create a local dummy DropdownMenuItem, for simplicity I created it.

class AddOrEditClaim extends StatefulWidget {
  @override
  AddOrEditClaimState createState() => AddOrEditClaimState();
}

class AddOrEditClaimState extends State<AddOrEditClaim> {
  UserPackages _selectedPackage;
  List<UserPackages> packageList = [];

  @override
  void initState() {
    super.initState();
    fetchPackages();
    _selectedPackage = UserPackages(categoryName: "vehicle insurance", packageId: "5675");
  }

  @override
  Widget build(BuildContext context) {
    List<DropdownMenuItem> items = packageList.map((item) {
      return DropdownMenuItem<UserPackages>(
        child: Text(item.categoryName),
        value: item,
      );
    }).toList();

    // if list is empty, create a dummy item
    if (items.isEmpty) {
      items = [
        DropdownMenuItem(
          child: Text(_selectedPackage.categoryName),
          value: _selectedPackage,
        )
      ];
    }

    return Scaffold(
      appBar: AppBar(title: Text('Add Claim')),
      body: Center(
        child: DropdownButton(
          items: items,
          onChanged: (newVal) => setState(() => _selectedPackage = newVal),
          value: _selectedPackage,
        ),
      ),
    );
  }

  fetchPackages() async {
    var resp = await http.get('http://www.mocky.io/v2/5da94ca131000058004e0769');
    if (resp.statusCode == 200)
      setState(() {
        packageList = parsePackages(resp.body);
        _selectedPackage = packageList[0];
      });
    else
      print("Error occurred");
  }

  List<UserPackages> parsePackages(String responseBody) {
    final parsedJson = json.decode(responseBody);
    final parsed = parsedJson.cast<Map<String, dynamic>>();
    return parsed.map<UserPackages>((json) => UserPackages.fromJson(json)).toList();
  }
}

class UserPackages {
  String categoryName;
  String packageId;

  UserPackages({this.categoryName, this.packageId});

  factory UserPackages.fromJson(Map<String, dynamic> json) {
    return UserPackages(
      packageId: json['packageId'] as String,
      categoryName: json['categoryName'] as String,
    );
  }
}

这篇关于无法使用抖动中的对象预先填充下拉菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆