根据上一个 Flutter 的选择更改下拉按钮的选择

Posted

技术标签:

【中文标题】根据上一个 Flutter 的选择更改下拉按钮的选择【英文标题】:Change selection of dropdown button according to the choice from the previous one, Flutter 【发布时间】:2022-01-02 00:44:25 【问题描述】:

我有 2 个DropdownButtonFormFields,我有一些汽车可供选择。我需要根据用户从 DropdownButtonFormField 中的第一个选择中选择的汽车型号更改按钮的第二个选择(即如果用户在第一个选择中选择梅赛德斯,在下面的 DropdownButtonFormField 中,我只想显示梅赛德斯的型号而不是,比方说,奥迪)。

我怎样才能做到这一点?代码如下:

String _make, _model;

/// List of cars and models
List<String> carList = [
    'Audi',
    'BMW',
    'Mercedes',
  ];
List<String> modelAudi = ['A6', 'A8', 'Q7',];
List<String> modelMercedes = ['E-Class', 'S-Class','Maybach'];
List<String> modelBMW = ['3-Series', 'X5', 'X7'];


/*two DropdownButtonFormFields, but the second one needs to match 
 it's car manufacturer selection from the carList selection
 (i.e. if you select Audi, it must only show the modelAudi list (A6,
 A8, Q7) in the second DropdownButtonFormField)
*/

 DropdownButtonFormField<String>(
          value: _make,
          items: carList
              .map((label) => DropdownMenuItem(
                    child: Text(label.toString()),
                    value: label,
                  ))
              .toList(),
          onChanged: (value) 
            setState(() 
              _make = value;
              print(value);
            );
          ,
        ),
 
DropdownButtonFormField<String>(
  value: _model,

/* here is where I need to implement logic 
that maps out the model names that matches the car maker
*/
  items: modelAudi
      .map((label) => DropdownMenuItem(
            child: Text(label.toString()),
            value: label,
          ))
      .toList(),
  onChanged: (value) 
    setState(() 
      _model = value;
      print(value);
    );
  ,
),                            

第一个按钮的下拉菜单:

很自然,因为我没有任何逻辑,所以无论我从汽车列表中选择什么,我都会将其作为模型选择,但我希望它仅映射出您选择的汽车列表中的模型。

【问题讨论】:

【参考方案1】:

这是 switch 语句的一个很好的用例。根据此示例为每个汽车制造商定义您的案例:

String _maker;
List chosenMakerModel;

switch (_maker) 
  case 'Audi':
   chosenMakerModel = modelAudi; 
    break;
  case 'BMW':
   // implement logic:
    break;
  case 'OTHER MANUFACTURER':
    // implement logic;
    break;
 

使用上面的示例代码,使用 chosenMakerModel 而不是 modelAudi

【讨论】:

是的,我实际上使用了一个 switch case,但我忘记返回一些东西让 UI 渲染它,比如 case 'Audi':return selectedMakerModel = modelAudi;,我是否正确?谢谢你让我意识到我的错误! @GrandMagus 不需要返回声明。在 Dart 中,return 语句会立即结束函数的执行,因此应该跳出 switch 语句。请接受我的回答,让我知道它是否适合您:) 我带了开关盒,用起来更清楚,谢谢。现在我还有另一个问题。 :) @GrandMagus 当然,您必须处理用户首先选择第二个的情况-我认为这是另一个主题,因此我没有回答以使其更简洁;)跨度> 【参考方案2】:

你可以创建一个模型选择方法来处理这种情况,比如

  List<String> _selectModel(String? modelName) 
    return modelName == carList[0]
        ? modelAudi
        : modelName == carList[1]
            ? modelMercedes
            : modelBMW; // initally it will have modelBMW
  

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


class MyProfileState extends State<StatefulWidget> 
  String? _make, _model;

  /// List of cars and models
  List<String> carList = ['Audi', 'BMW', 'Mercedes'];
  List<String> modelAudi = ['A6', 'A8', 'Q7'];
  List<String> modelMercedes = ['E-Class', 'S-Class', 'Maybach'];
  List<String> modelBMW = ['3-Series', 'X5', 'X7'];

  List<String> _selectModel(String? modelName) 
    return modelName == carList[0]
        ? modelAudi
        : modelName == carList[1]
            ? modelMercedes
            : modelBMW;
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
        body: Column(
      children: [
        DropdownButtonFormField<String>(
          value: _make,
          items: carList
              .map((label) => DropdownMenuItem(
                    child: Text(label.toString()),
                    value: label,
                  ))
              .toList(),
          onChanged: (value) 
            setState(() 
              _make = value;
              _model = null;
              print(value);
            );
          ,
        ),
        DropdownButtonFormField<String>(
          value: _model,
          items: _selectModel(_make)
              .map((label) => DropdownMenuItem(
                    child: Text(label.toString()),
                    value: label,
                  ))
              .toList(),
          onChanged: (value) 
            setState(() 
              _model = value;
              print(value);
            );
          ,
        ),
      ],
    ));
  

【讨论】:

我更喜欢用模型创建另一个列表,而不是 carList 我将使用索引并使用newList[index]。但我认为最好将 Map&lt;String,List&lt;String?&gt;&gt; modelName 与 carNames 一起使用 @GrandMagus 取决于您的喜好。嵌套或更长的三元表达式可能非常混乱,因此应该用 if-else 语句代替。如果您使用后者或 switch 语句来控制您的代码执行取决于您!就个人而言,我更喜欢 switch 语句:) Switch case 需要const 值来检查,在某些情况下我们没有。并且可能会出现我在回答中描述的第二个问题,仍然可以将其作为答案接受,是的,您可以使用 if else 所需的逻辑,但对于像这样的简单情况,我更喜欢三元。 经过一些测试并再次完整阅读两个答案,我必须同意@YeasinSheikh,我仍然可以使用开关盒,但我必须有一个默认值并进行第二次选择null再次切换第一个选择时。也切换了接受的答案。

以上是关于根据上一个 Flutter 的选择更改下拉按钮的选择的主要内容,如果未能解决你的问题,请参考以下文章

想从下拉列表中选择选项并根据所选选项更改按钮的标题...如何?

如何根据其他下拉选择将本地 Json 加载到 Flutter DropDown?

如何根据 Flutter 中的条件导航到页面

如果单击按钮,下拉列表选项会更改(VueJS 和 Laravel 6)

根据选定的选项卡更改 Tabcontrol 外部的控件属性

jQuery根据下拉列表中的选择将行移动到另一个表