1

我试图让用户在第一个下拉列表中选择项目的类型,然后在第二个下拉列表中从其相应的可用颜色中进行选择。但是,当我选择了一种颜色(即白色)后,现在想要切换到另一个没有这种颜色的项目时,会抛出一个错误:

"There should be exactly one item with [DropdownButton]'s value: white. \nEither zero or 2 or more
[DropdownMenuItem]s were detected with the same value"

请帮忙,我已经尝试在不同的地方设置状态来更新值,但这个错误仍然发生。

以下是我的代码片段:

StreamBuilder<QuerySnapshot>(
    stream: mainItemsSnapshots,
    builder: (context, snapshot) {
    if (snapshot.hasError) return Text("Error");
    switch (snapshot.connectionState) {
        case ConnectionState.waiting:
        return Center(child: CircularProgressIndicator());
        default:
        {
            List<DropdownMenuItem> dropdownMenuItems =
                snapshot.data.documents
                    .map((DocumentSnapshot mainItem) {
            return new DropdownMenuItem<String>(
                value: mainItem.documentID,
                child: Text(mainItem.documentID),
            );
            }).toList();
            return DropdownButtonFormField<String>(
            items: dropdownMenuItems,
            onChanged: (String value) {
                if (value != tempMainItemType) {
                    setState(() {
                    tempMainItemType = value;
                    tempItemColorsList.clear();
                    tempItemColorsList = [];
                    tempMainItemColor = null;
                    });
                }
                
                if (tempItemColorsList.isEmpty && value != null) {
                tempItemColorsList = snapshot.data.documents
                    .where((element) => element.documentID == value)
                    .first
                    .data["colors"]
                    .keys
                    .map((color) => color.toString())
                    .toList()
                    .cast<String>();
                }
                setState((){});
            },
            onSaved: (String value) {
                _order.mainItemType = value;
            },
            value: tempMainItemType,
            );
        }
    }
    },
),

// Main color
if (tempItemColorsList?.isNotEmpty)
    Padding(
    padding: const EdgeInsets.only(top: spacingGeneral),
    child: textFieldLabel(context, "Main color"),
    ),
if (tempItemColorsList?.isNotEmpty)
    DropdownButtonFormField(
    items: tempItemColorsList.map((String color) {
        return new DropdownMenuItem<String>(
        value: color,
        child: Text(color),
        );
    }).toList(),
    onSaved: (String value) {
        _order.mainColor = value;
    },
    value: tempMainItemColor,
    onChanged: (String value) {
        setState(() {
        tempMainItemColor = value;
        });
    },
    ),
4

1 回答 1

0

这可能为时已晚,但您可以创建一个Map<String, List<String>>键是第一个下拉列表的项目,值将是第二个下拉列表的项目。

在这里,我创建了一个状态来存储第一个下拉列表的选定项。然后我用它来映射第二个下拉列表的项目。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SampleDD(),
    );
  }
}

class SampleDD extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: DoubleDropdown(
          items: <String, List<String>>{
            'dark colors': ['black', 'gray', 'brown'],
            'light colors': ['white', 'yellow', 'green'],
          },
          onChangedFirst: (val) => print('Selected first: $val'),
          onChangedSecond: (val) => print('Selected second: $val'),
        ),
      ),
    );
  }
}

class DoubleDropdown extends StatefulWidget {
  DoubleDropdown({
    @required this.items,
    @required this.onChangedFirst,
    @required this.onChangedSecond,
  });

  final Map<String, List<String>> items;
  final ValueChanged<String> onChangedFirst;
  final ValueChanged<String> onChangedSecond;

  @override
  _DoubleDropdownState createState() => _DoubleDropdownState();
}

class _DoubleDropdownState extends State<DoubleDropdown> {
  String selectedKey;

  @override
  void initState() {
    super.initState();
    selectedKey = widget.items.keys.first;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        _buildFirstDropdown(),
        _buildSecondDowndown(),
      ],
    );
  }

  Widget _buildFirstDropdown() => DropdownButtonFormField<String>(
        items: widget.items.keys.map((e) {
          return DropdownMenuItem<String>(
            child: Text(e),
            value: e,
          );
        }).toList(),
        onChanged: (val) {
          setState(() => selectedKey = val);
          widget.onChangedFirst(val);
        },
        value: selectedKey,
      );

  Widget _buildSecondDowndown() => DropdownButtonFormField<String>(
        items: widget.items[selectedKey].map((e) {
          return DropdownMenuItem<String>(
            child: Text(e),
            value: e,
          );
        }).toList(),
        onChanged: widget.onChangedSecond,
        value: widget.items[selectedKey].first,
      );
}
于 2020-12-28T09:10:35.553 回答