Должен быть ровно один элемент со значением [DropdownButton].

Я создаю приложение для системы электронной коммерции, которая может отправлять данные на сервер. Существует несколько категорий элементов, которые имеют разные и настраиваемые значения. Например, категория ноутбука может иметь атрибуты процессор, оперативная память, размер хранилища. Некоторые из этих атрибутов являются текстовыми полями (например, модель), в то время как другие должны быть раскрывающимися списками (например, процессор — ядро ​​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-запрос на сервер. Имейте в виду, что количество раскрывающихся списков (атрибутов) различается для каждой категории. Второй вопрос, не столь важный, но есть ли способ, с помощью которого я могу присвоить имя каждому раскрывающемуся списку, используя столбец «Имя» атрибутов в файле json.

person Abdi Nur    schedule 27.01.2021    source источник


Ответы (2)


Попробуйте установить для другого раскрывающегося списка значение null при изменении значения раскрывающегося списка в методе onChanged.

person Community    schedule 27.01.2021
comment
Это чтобы не видеть ошибку или получить доступ к значениям? Потому что я почти уверен, что не имеет смысла устанавливать другие значения раскрывающегося списка равными нулю, если пользователи уже выбрали значение из раскрывающегося списка. - person user3659497; 27.01.2021
comment
я почти уверен, что null будет работать, потому что это работало для меня в прошлом - person ; 27.01.2021

Проблема связана с присвоенным значением и списком элементов раскрывающегося списка.

Обратите внимание, что значение раскрывающегося списка может быть только значением из элементов раскрывающегося списка. А для пользовательских значений вам придется сравнить значение выбранного элемента и указать индекс элементов в качестве текущего значения. Надеюсь, вы понимаете мои опасения.

Следуйте приведенному ниже коду:

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;
}
person Gourango Sutradhar    schedule 27.01.2021
comment
Я попробовал ваш код, и он говорит, что "attributeid" получателя был вызван с нулевым значением. Получатель: null Попытка вызова: attributeid - person Abdi Nur; 27.01.2021
comment
Я отредактировал ответ. Пожалуйста, проверь это. - person Gourango Sutradhar; 27.01.2021
comment
опять та же ошибка - person Abdi Nur; 27.01.2021