#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
при повторном переключении первого выбора. Также переключил принятый ответ.