flutter 应该正好有一个项目具有[DropdownButton]的值

pgx2nnw8  于 2023-04-07  发布在  Flutter
关注(0)|答案(4)|浏览(234)

我正在为一个电子商务系统构建一个应用程序,它可以将数据发布到服务器。有多个项目类别,它们具有不同的可定制值。例如,笔记本电脑类别可以具有处理器,内存,存储大小属性。其中一些属性是文本框(例如型号),而其他需要下拉(例如处理器核心i7,i5等...)。属性的数量不能固定,因为它取决于类别(可能随时添加或删除)
我试图构建一个表单,它将根据属性类型(AttributeType列)将此属性显示为文本框或下拉列表。我能够同时显示文本框和下拉列表(成功地显示了它们的元素。我遇到的问题是访问下拉列表值以创建对服务器的发布请求。
下面是代码

FutureBuilder<FormListModel>(
                future: _formList,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return ListView.builder(
                      primary: false,
                      scrollDirection: Axis.vertical,
                      shrinkWrap: true,
                      itemCount: snapshot.data.customattributes.length,
                      itemBuilder: (context, index) {
                        var item = snapshot.data.customattributes[index];
                        print(item.name);
                        
                        if (item.AttributeType == 'Text') {
                          return Container(
                            //padding: EdgeInsets.only(top: 8),
                            margin:
                                EdgeInsets.only(top: 15, left: 15, right: 15),
                            child: Column(
                              children: [
                                Form(
                                  child: TextFormField(
                                    controller: model_controller,
                                    decoration: InputDecoration(
                                      contentPadding: EdgeInsets.symmetric(
                                          vertical: 10, horizontal: 10),
                                      labelText: item.name,
                                      border: OutlineInputBorder(
                                        borderSide: BorderSide(
                                            color: Colors.blueAccent),
                                      ),
                                    ),
                                    onChanged: (value) {
                                      //print(model_controller.text);
                                    },
                                  ),
                                ),
                              ],
                            ),
                          );
                        } else if (item.AttributeType == 'Selectlist') {
                          return Container(
                            //padding: EdgeInsets.only(top: 8),
                            margin:
                                EdgeInsets.only(top: 20, left: 15, right: 15),
                            child: Column(
                              children: [
                                Form(
                                  child: InputDecorator(
                                    decoration: InputDecoration(
                                      contentPadding: EdgeInsets.symmetric(
                                          vertical: 12, horizontal: 12),
                                      labelText: item.name,
                                      labelStyle: TextStyle(
                                          fontSize: 20,
                                          color: Colors.blueAccent),
                                      border: const OutlineInputBorder(),
                                    ),
                                    child: DropdownButtonHideUnderline(
                                      child: DropdownButton(
                                        isDense: true,
                                        icon: Icon(Icons.keyboard_arrow_down),
                                        value: selectedAttribute,
                                        onChanged: (newValue) {
                                          setState(() {
                                            selectedAttribute = newValue;
                                          });
                                        },
                                        //decoration: InputDecoration(border: InputBorder.none),
                                        items: item.children
                                            .map<DropdownMenuItem>((items) {
                                          return DropdownMenuItem<String>(
                                            child: Row(
                                              children: [
                                                Padding(
                                                  padding:
                                                      EdgeInsets.only(top: 7),
                                                  child: Text(items.element),
                                                ),
                                              ],
                                            ),
                                            value: items.element,
                                          );
                                        }).toList(),
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          );
                        } else {
                          return null;
                        }
                      },
                    );
                  } else {
                    return Container();
                  }
                }),

下面是我们从服务器获取的json文件,用于使用ListView.builder创建表单

{
    "category": {
        "CategoryName": "Laptops",
        "CategoryID": 34
    },
    "customattributes": [
        {
            "Name": "Model",
            "AttributeType": "Text",
            "AttributeID": 7
        },
        {
            "Name": "Processor",
            "AttributeType": "Selectlist",
            "AttributeID": 2,
            "Children": [
                {
                    "Element": "Intel Core i3"
                },
                {
                    "Element": "Intel Core i5"
                },
                {
                    "Element": "Intel Core i7"
                }
            ]
        },
        {
            "Name": "Storage Size",
            "AttributeType": "Selectlist",
            "AttributeID": 1,
            "Children": [                
                {
                    "Element": "1TB"
                },
                {
                    "Element": "2TB"
                },
                {
                    "Element": "2.5TB"
                }
            ]
        },
        {
            "Name": "RAM",
            "AttributeType": "Selectlist",
            "AttributeID": 3,
            "Children": [
                {
                    "Element": "12GB"
                },
                {
                    "Element": "16GB"
            ]
        }
    ],
    
}

这是表格

当我从下拉列表中选择任何值时,我得到一个错误,它说:应该只有一个项目具有[DropdownButton]的值

1.那么我如何访问每个下拉列表的值,以便我可以向服务器发出http post请求。请记住,每个类别的下拉列表(属性)的数量是不同的。第二个问题,不是很重要,但是否有一种方法可以使用json文件中属性的“名称”列为每个下拉列表分配名称。

i7uq4tfw

i7uq4tfw1#

在onChanged方法中更改下拉列表值时,尝试将其他下拉列表值设置为null

s4n0splo

s4n0splo2#

这个问题是关于分配的值和下拉列表的项目列表。
请注意,下拉列表的值只能是下拉列表项中的值。对于自定义值,您必须比较所选项目的值,并将项目的索引作为当前值。希望您理解我的担忧。
执行以下代码:

value : getSelectedValue(yourValue);
...
getSelectedValue(yourValue){
    //add this line of code
    if(yourValue == null) return null;
    for(value in dropDownItems){
        if(value.id == yourValue.id) return value;
    }
    return null;
}
lh80um4z

lh80um4z3#

我也有同样的问题…我设法通过检查我的列表是否为空来解决它…如果是,我将值设置为null,否则选择列表上的第一个项目

value: Provider.of<DepositProvider>(context)
                          .paymentMethods.isNotEmpty ?Provider.of<DepositProvider>(context)
                          .paymentMethods.first : null,
qqrboqgw

qqrboqgw4#

你可以像这样解决:

String? _selectedItem;

  @override
  void initState() {
    _selectedItem = widget.items?[0];
    super.initState();
  }

  void _changeSelectedPickList(String? pickListData) {
    setState(() {
      _selectedItem = pickListData;
    });
    widget.onChanged(pickListData);
  }

  getSelectedValue(String yourValue) {
    if (yourValue == null) return null;
    for (var value in widget.items!) {
      if (value == yourValue) return value;
    }
    return null;
  }

getSelectedValue函数解决了我的问题完整代码如下:

import 'package:flutter/material.dart';
import 'package:kartal/kartal.dart';

import '../../../feature/basket/viewmodel/cubit/basket_cubit.dart';
import '../profile/payment_dropdown_text_widget.dart';

class CurrencyListDropdown extends StatefulWidget {
  const CurrencyListDropdown(
      {Key? key,
      required this.items,
      this.selectedItems,
      required this.onChanged,
      required this.hint,
      this.basketCubit})
      : super(key: key);
  final List<String?>? items;
  final BasketCubit? basketCubit;

  final String? selectedItems;
  final String hint;

  final void Function(String? model) onChanged;
  @override
  State<CurrencyListDropdown> createState() => _CurrencyListDropdownState();
}

class _CurrencyListDropdownState extends State<CurrencyListDropdown> {
  String? _selectedItem;

  @override
  void initState() {
    _selectedItem = widget.items?[0];
    super.initState();
  }

  void _changeSelectedPickList(String? pickListData) {
    setState(() {
      _selectedItem = pickListData;
    });
    widget.onChanged(pickListData);
  }

  getSelectedValue(String yourValue) {
    if (yourValue == null) return null;
    for (var value in widget.items!) {
      if (value == yourValue) return value;
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return DropdownButtonFormField<String?>(
        value: getSelectedValue(_selectedItem!),
        isExpanded: true,
        isDense: false,
        decoration: InputDecoration(
          isCollapsed: true,
          contentPadding: EdgeInsets.zero,
          border:
              OutlineInputBorder(borderSide: BorderSide(color: context.colorScheme.onErrorContainer.withOpacity(0.7))),
          enabledBorder:
              OutlineInputBorder(borderSide: BorderSide(color: context.colorScheme.onErrorContainer.withOpacity(0.7))),
        ),
        hint: Center(
            child: Text(
          widget.hint,
          style: context.textTheme.titleSmall,
          textAlign: TextAlign.center,
        )),
        onChanged: _changeSelectedPickList,
        items: widget.items?.map((e) {
          return _dropdownItem(e, context);
        }).toList());
  }

  DropdownMenuItem<String> _dropdownItem(String? e, BuildContext context) {
    return DropdownMenuItem(
        value: e,
        child: PaymentDropdownTextWidget(
          label: e,
        ));
  }
}

相关问题