You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

修复步骤

  1. 建立章节名称到id的映射
    添加一个Map来关联阿拉伯文章节名称和pagesPerSurah中的数字key:

    final surahNameToId = {
      'بقرة': 1,
      'البقرة': 2,
      'آل عمران': 3,
      'النساء': 4,
      'المائدة': 5,
      // 补充所有需要的章节名称与id的对应关系
    };
    
  2. 修改三级Dropdown的数据源获取逻辑
    替换原来的int.parse(selectedSurah!.substring(6)),通过映射获取对应的id:

    items: (selectedSurah != null)
        ? pagesPerSurah[surahNameToId[selectedSurah!]]
            ?.map((page) => DropdownMenuItem<String>(
                value: page, child: Text(page)))
            .toList() ?? [] // 处理映射不存在时的空情况
        : [],
    
  3. 修正三级Dropdown的validator文案
    将validator中的错误提示改为对应页面的内容:

    validator: (val) {
      return val != '' ? null : 'Please select page';
    },
    

内容的提问来源于stack exchange,提问作者sulli110

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:24:51