Flutter如何设置FormBuilderDropdown默认选中解决级联下拉禁用问题
问题根源
- 父级
FormBuilderDropdown设置的initialValue仅负责组件初始状态的显示值,不会自动触发onChanged回调,写在onChanged里的子级数据加载方法fetchSite在页面初始化时根本没执行,子下拉框没有可选项自然处于禁用状态 - 现有代码的下拉选项映射逻辑存在错误:所有
DropdownMenuItem的value都绑定了固定的外部变量cityChoosen,没有和遍历到的当前城市项绑定,会导致值匹配、选中态错乱
修复方案
1. 初始化阶段主动触发级联加载
不要等用户手动点击父下拉框才加载子级数据,在State的初始化生命周期里,首帧渲染完成后主动拿父级初始值调用子级加载逻辑:
@override void initState() { super.initState(); // 初始化父级下拉框默认值,和你传入的initialValue保持一致 citySelected = widget.callLocationModel.CityName; // 首帧渲染完成后主动加载子级数据 WidgetsBinding.instance.addPostFrameCallback((_) { fetchSite(citySelected); // 存在多级级联的话,此处可按依赖顺序依次触发下一级加载 }); }
2. 修正父下拉框的选项值绑定错误
把下拉选项的value和当前遍历项绑定,不要使用固定外部变量,修正后的父下拉框代码如下:
padding: const EdgeInsets.all(12.0), child: FormBuilderDropdown( name: 'City', decoration: const InputDecoration( labelText: 'City', ), allowClear: true, initialValue: citySelected, validator: FormBuilderValidators.compose([ FormBuilderValidators.required(context) ]), items: cityList .map((cityItem) => DropdownMenuItem( // 绑定当前遍历的城市项,类型和citySelected保持一致即可 value: cityItem, child: Text(cityItem.toString()), )) .toList(), onChanged: (value) { setState(() { citySelected = value; // 清空下级下拉框的旧数据,避免切换城市后显示旧站点 siteSelected = null; siteList = []; // 加载当前城市对应的站点数据 fetchSite(citySelected); }); }, ),
3. 调整子下拉框启用逻辑、同步设置初始值
子下拉框不要加「父级是否手动点击过」这类判断,直接根据「子选项列表是否非空」控制启用状态即可,参考fetchSite实现:
Future<void> fetchSite(dynamic cityValue) async { // 调用接口获取当前城市下的站点列表 final siteRes = await siteApi.getListByCity(cityValue); setState(() { siteList = siteRes.data; // 自动填充默认选中值,优先取传入的默认值,没有就取列表第一项 siteSelected = widget.callLocationModel.SiteName ?? siteList.first; // 存在下一级级联的话,此处继续触发下一级加载逻辑 }); }
子下拉框的enabled属性直接设置为siteList.isNotEmpty即可,加载完选项后会自动进入可交互状态,不需要用户手动点击父级触发。
多级级联场景下,每次父级值变更都要先清空所有下级的选中值、选项列表,再重新加载对应下级数据,避免出现数据串扰。
内容的提问来源于stack exchange,提问作者Digvijay Zite
相关产品推荐
相关产品推荐

