【问题标题】:Dynamic Drop Down Field based on selection基于选择的动态下拉字段
【发布时间】:2022-01-05 11:34:38
【问题描述】:

我有一个相当复杂的表单,下拉列表会根据之前的选择而变化。例如,如果我选择送货或取货选项,下一个下拉菜单将基于该选择并显示商店列表或送货选项。

我有以下代码并尝试了几个选项,但下拉菜单似乎没有根据选择更新,但我不知道为什么,因为它应该随着状态变化而刷新。

对此有最佳方法的建议吗?我认为这可能与需要唯一的 Key 有关,但这似乎并不能解决问题,并且还会导致其他问题,例如在其他字段更改时清除所选项目。

问题: 如何根据之前在 Dart/Flutter 中的表单字段选择提供动态下拉菜单?

              DropDownInputField(
                inputList: const [
                  'Delivery',
                  'Pickup',
                ],
                onchanged: (selection) {
                  setState(() {
                    order.shippingOption = selection;
                  });
                },
                name: 'Shipping Option',
              ),
              const SizedBox(
                height: 20,
              ),
              DropDownInputField(
                inputList: retrieveList(order.shippingOption),
                onchanged: (value) => order.deliveryOption = value,
                name: 'Delivery Options',
              ),

选项生成函数

List<String> retrieveList(String shippingOption) {
    switch (shippingOption.toLowerCase()) {
      case "delivery":
        return [
          'Standard',
          'Express',
        ];
        break;
      case "pickup":
        return [
          'Store 1',
          'Store 2',
        ];
        break;

状态类

class _ShippingFormScreenState extends State<ShippingFormScreen>
    with SingleTickerProviderStateMixin {
  TabController tabController;
  Order order;

【问题讨论】:

  • order.shippingOption是状态变量吗?需要查看有状态的小部件类和变量声明。
  • 是的。为了清楚起见,只是在问题中添加了。

标签: flutter dart


【解决方案1】:

generation Function 将决定第二个下拉项目。但是如果你点击选择第二个下拉项目1st,它会通过错误。要处理这种情况,您还需要更新第二个下拉值。您可以设置第二个下拉值 = null。因此,我们需要使用可为空的字符串作为选择值。

在第一个 DropDownFiled onChanged 使第二个下拉值为空。

DropDownInputField(
                inputList: const [
                  'Delivery',
                  'Pickup',
                ],
                onchanged: (selection) {
                  setState(() {
                    order.shippingOption = selection;
                    order.deliveryOption = null;
                  });
                },
                name: 'Shipping Option',
              ),

第二个下拉菜单似乎还可以。但请确保将这些字段设为可为空。 我会鼓励你检查this

【讨论】:

  • 为什么将order.deliveryOption 设置为null?没有给出类 Order 的定义,但根据其余代码,可以安全地假设没有可为空的字段。
【解决方案2】:

您必须使用 onChanged 禁用基于顶部下拉菜单的底部下拉菜单

从文档中,像这样禁用:

如果 items 或 onChanged 为 null,按钮将被禁用,向下箭头将变灰,并且 disabledHint 将显示(如果提供)

所以我们将禁用底部下拉菜单并查看订单是否更改。 您应该将底部下拉 onChanged 函数更改为此

              items: retrieveList(order.shippingOption),
              onChanged: order.shippingOption == null
                  ? null
                  : (value) {
                      setState(() {
                        order.deliveryOption = value!;
                      });
                    },

并将retrieveList 更改为:



  List<String> retrieveList(String? shippingOption) {
    if (shippingOption == null) return [];

    switch (shippingOption.toLowerCase()) {
      case "delivery":
        return [
          'Standard',
          'Express',
        ];

      case "pickup":
        return [
          'Store 1',
          'Store 2',
        ];

      default:
        throw Exception('Unknown shipping option');
    }
  }
}

小部件的完整代码

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Order order = Order();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            DropDownInputField(
              items: const [
                'Delivery',
                'Pickup',
              ],
              onChanged: (value) {
                setState(() {
                  order.shippingOption = value!;
                });
              },
              value: order.shippingOption,
              name: 'Shipping Option',
            ),
            const SizedBox(
              height: 20,
            ),
            DropDownInputField(
              items: retrieveList(order.shippingOption),
              onChanged: order.shippingOption == null
                  ? null
                  : (value) {
                      setState(() {
                        order.deliveryOption = value!;
                      });
                    },
              name: 'Delivery Options',
              value: order.deliveryOption,
            ),
          ],
        ),
      ),
    );
  }

  List<String> retrieveList(String? shippingOption) {
    if (shippingOption == null) return [];

    switch (shippingOption.toLowerCase()) {
      case "delivery":
        return [
          'Standard',
          'Express',
        ];

      case "pickup":
        return [
          'Store 1',
          'Store 2',
        ];

      default:
        throw Exception('Unknown shipping option');
    }
  }
}

class Order {
  String? shippingOption;
  String? deliveryOption;
}

class DropDownInputField extends StatelessWidget {
  const DropDownInputField({
    Key? key,
    required this.items,
    required this.onChanged,
    required this.value,
    required this.name,
  }) : super(key: key);
  final List<String> items;
  final ValueChanged<String?>? onChanged;
  final String? value;
  final String name;
  @override
  Widget build(BuildContext context) {
    return DropdownButton<String>(
      value: value,
      hint: Text(name),
      items: <DropdownMenuItem<String>>[
        ...items.map((e) => DropdownMenuItem(
              child: Text(e),
              value: e,
            ))
      ],
      onChanged: onChanged,
    );
  }
}

【讨论】:

    猜你喜欢
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    相关资源
    最近更新 更多