Измените выбор выпадающей кнопки в соответствии с выбором из предыдущей, Трепещите

#flutter #mobile #flutter-dropdownbutton

Вопрос:

У меня есть 2 DropdownButtonFormField с, где у меня есть выбор автомобилей. Мне нужно изменить второй выбор кнопок в соответствии с моделью автомобиля, выбранной пользователем из первого выбора в поле Раскрывающаяся кнопка (т. Е., Если пользователь выбирает Mercedes в первом, в поле Раскрывающаяся кнопка ниже, я хочу отображать только модели Mercedes, а не, скажем, Audi).

Как я могу этого достичь? Вот код:

 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

Комментарии:

1. Да, я на самом деле использовал случай переключения, но я забыл вернуть что-то для пользовательского интерфейса, чтобы отобразить его, например, случай «Audi»: return chosenMakerModel = modelAudi;, я прав или нет? Спасибо, что заставил меня осознать мою ошибку!

2. @GrandMagus Заявление о возврате не должно требоваться. В Dart оператор return немедленно завершает выполнение функции и, следовательно, должен выйти из оператора switch. Пожалуйста, дайте мне знать, если это сработает для вас, приняв мой ответ 🙂

3. Я пошел с корпусом выключателя, он более понятен для меня, спасибо. Теперь у меня есть еще одна проблема. 🙂

4. @GrandMagus, Конечно, вы должны справиться с тем, что пользователь выбирает 2 — е место первым-это, на мой взгляд, еще одна тема, на которую я поэтому не ответил, чтобы сделать ее более краткой 😉

Ответ №2:

Вы можете создать метод выбора модели, чтобы справиться с этой ситуацией, например

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

 

Это определит второй пункт выпадающего списка. Если вы нажмете, чтобы выбрать второй выпадающий пункт 1-го, он будет содержать ошибки. Чтобы справиться с этой ситуацией, вам также необходимо обновить второе значение выпадающего списка. Вы можете установить второй раскрывающийся 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);
            });
          },
        ),
      ],
    ));
  }
}
 

Комментарии:

1. Я бы предпочел создать другой список с моделями, и вместо списка я буду использовать индекс и использовать newList[index] . Но я думаю, что лучше будет использовать Map<String,List<String?>> имя модели с именами карНамов

2. @GrandMagus Зависит от ваших предпочтений. Вложенные или более длинные тернарные выражения могут быть очень запутанными и, следовательно, должны быть заменены операторами if-else. Если вы используете последнее или переключаете операторы для управления выполнением кода, это зависит от вас! Лично я предпочитаю заявления о переключении 🙂

3. Случай переключения требует const проверки значения, а в некоторых случаях у нас его нет. И может возникнуть вторая проблема, которую я описал в своем ответе, все равно это принимается как ответ, и да, вы можете использовать, если хотите, логику, но для простых случаев, подобных этому, я предпочитаю троичный .

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