Flutter三级联动Dropdown报错:选择二级下拉框时三级下拉框异常
Flutter三级联动Dropdown报错修复
问题现象
实现三个相互依赖的Dropdown组件:
- 一级Dropdown选择后,二级Dropdown能正常加载对应数据
- 选择二级Dropdown时,三级Dropdown抛出错误,无法填充数据
数据源
一级Dropdown数据源
final List<String> juzList = List<String>.generate(30, (i) => ('Juz ${i + 1}'));
二级Dropdown数据源
final surahPerJuz = [ ['بقرة'], [ 'البقرة', 'آل عمران', ], ['آل عمران', 'النساء', 'المائدة'] ];
三级Dropdown数据源
final pagesPerSurah = { 1: List<String>.generate(100, (i) => ('Page ${i + 1}')), 2: List<String>.generate(101, (i) => ('Page ${i + 1}')), 3: List<String>.generate(200, (i) => ('Page ${i + 1}')), // ... 补充剩余章节的映射 };
组件代码
一级Dropdown代码
FormField( builder: (FormFieldState state) { return InputDecorator( decoration: kTextInputDecoration.copyWith( labelText: 'Select Juz', errorText: state.hasError ? state.errorText : null, ), child: DropdownButtonHideUnderline( child: DropdownButton( value: selectedJuz, isDense: true, onChanged: (value) { setState(() { selectedJuz = value; selectedSurah = null; selectedPage = null; }); }, items: juzList.map((value) { return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), ), ), ); }, validator: (val) { return val != '' ? null : 'Please select juz'; }, ),
二级Dropdown代码
FormField( builder: (FormFieldState state) { return InputDecorator( decoration: kTextInputDecoration.copyWith( labelText: 'Select Surah', errorText: state.hasError ? state.errorText : null, ), child: DropdownButtonHideUnderline( child: DropdownButton<String>( value: selectedSurah, isDense: true, onChanged: (value) { setState(() { selectedSurah = value; selectedPage = null; }); }, items: (selectedJuz != null) ? surahPerJuz[int.parse(selectedJuz!.substring(4)) - 1] .map((surah) => DropdownMenuItem<String>( value: surah, child: Text(surah))) .toList() : [], ), ), ); }, validator: (val) { return val != '' ? null : 'Please select surah'; }, ),
三级Dropdown代码
FormField( builder: (FormFieldState state) { return InputDecorator( decoration: kTextInputDecoration.copyWith( labelText: 'Select Page', errorText: state.hasError ? state.errorText : null, ), child: DropdownButtonHideUnderline( child: DropdownButton<String>( value: selectedPage, isDense: true, onChanged: (value) { setState(() { selectedPage = value; }); }, items: (selectedSurah != null) ? pagesPerSurah[int.parse(selectedSurah!.substring(6))] ?.map((page) => DropdownMenuItem<String>( value: page, child: Text(page))) .toList() : [], ), ), ); }, validator: (val) { return val != '' ? null : 'Please select surah'; // 这里文案错误,应该是'Please select page' }, ),
错误信息
选择二级Dropdown时触发错误:
error: Invalid number (at character 1)
报错原因及修复方案
报错原因
三级Dropdown中使用selectedSurah!.substring(6)尝试提取数字,但selectedSurah是阿拉伯文名称(比如بقرة),字符串长度远小于6,substring(6)会返回空字符串或无效内容,传给int.parse()时就会抛出"Invalid number"错误。同时,阿拉伯文名称和pagesPerSurah的数字key没有直接对应关系,无法通过截取字符串获取有效id。
修复步骤
建立章节名称到id的映射
添加一个Map来关联阿拉伯文章节名称和pagesPerSurah中的数字key:final surahNameToId = { 'بقرة': 1, 'البقرة': 2, 'آل عمران': 3, 'النساء': 4, 'المائدة': 5, // 补充所有需要的章节名称与id的对应关系 };修改三级Dropdown的数据源获取逻辑
替换原来的int.parse(selectedSurah!.substring(6)),通过映射获取对应的id:items: (selectedSurah != null) ? pagesPerSurah[surahNameToId[selectedSurah!]] ?.map((page) => DropdownMenuItem<String>( value: page, child: Text(page))) .toList() ?? [] // 处理映射不存在时的空情况 : [],修正三级Dropdown的validator文案
将validator中的错误提示改为对应页面的内容:validator: (val) { return val != '' ? null : 'Please select page'; },
内容的提问来源于stack exchange,提问作者sulli110
相关产品推荐
相关产品推荐

