Flutter问题:关联下拉菜单无法根据选中分类显示产品选项
Flutter关联下拉菜单问题:产品下拉无法根据选中分类展示对应选项
我是Flutter新手,尝试创建包含分类和产品的关联下拉菜单。分类下拉可正常显示,但产品下拉无法根据选中的分类值展示对应选项。我尝试用where方法和contains都无效,求解决思路。
localData.dart
import 'package:flutter/material.dart'; class LocalData with ChangeNotifier { static const List<Map<String, dynamic>> _categories = [ {'id': 1, 'name': 'Electronics'}, {'id': 2, 'name': 'Gaming'}, {'id': 3, 'name': 'Accessories'}, ]; static List<Map<String, dynamic>> get categories { return [..._categories]; } static List<Map<String, dynamic>> _products = [ { 'id': 1, 'name': 'Smartphone', 'categoriesId': [1] }, { 'id': 2, 'name': 'Laptop', 'categoriesId': [2, 3] }, { 'id': 3, 'name': 'iPods', 'categoriesId': [1, 3] }, ]; static List<Map<String, dynamic>> get products{ return [..._products]; } }
产品数据中的categoriesId字段与分类数据的id关联。我的页面代码如下:
home.dart
class _HomePageState extends ConsumerState<HomePage> { int? category; int? product; List<Map<String, dynamic>> loadProd = []; @override Widget build(BuildContext context) { final themeService = ref.watch(themeServiceProvider); final ancScaffold = Scaffold.maybeOf(context); getProductsOptions() { loadProd = LocalData.products .where( (prod) => prod['categoriesId'] == category, ) .toList(); if (LocalData.products.isNotEmpty) { return loadProd.map((val) { return DropdownMenuItem( value: val['id'], child: Container(child: Text(val['name']))); }).toList(); } } return Scaffold( appBar: AppBar( bottom: themeService.appbarBottom(), elevation: 0, ), body: SingleChildScrollView( child: Column( children: [ Material( child: Container( child: Form( child: Column( children: [ SizedBox( child: DropdownButtonFormField( value: category, isExpanded: true, decoration: InputDecoration( labelText: 'Categories', ), items: LocalData.categories.map((cat) { return DropdownMenuItem( value: cat['id'], child: Container(child: Text(cat['name']))); }).toList(), onChanged: (value) { setState(() { if (value == null) { return; } category = value as int; //print(categories); }); }, ), ), SizedBox( child: DropdownButtonFormField( value: product, isExpanded: true, decoration: InputDecoration( labelText: 'Products', ), //value: categories, items: getProductsOptions(), onChanged: (prod) { setState(() { if (prod == null) { return; } product = prod as int; }); }, ), ), ], ), ), ), ), ], ), ), ); } }
问题根源
核心错误是产品筛选逻辑不匹配:
prod['categoriesId']是数组类型(如[1]、[2,3]),你直接用==和单个整数category比较,永远无法匹配。- 选中新分类后未重置产品选中值,可能导致选中的产品不在新筛选列表中,引发异常。
getProductsOptions中的LocalData.products.isNotEmpty判断多余,即使产品列表为空,map也会返回空列表,不会报错。
修复方案
1. 修正筛选逻辑
将筛选条件改为检查数组是否包含选中的分类ID,注意要先将prod['categoriesId']转为List<int>类型:
getProductsOptions() { loadProd = LocalData.products .where((prod) => (prod['categoriesId'] as List<int>).contains(category)) .toList(); return loadProd.map((val) { return DropdownMenuItem( value: val['id'], child: Container(child: Text(val['name']))); }).toList(); }
2. 选中分类时重置产品选中状态
在分类下拉的onChanged回调中,设置新分类后将product置为null:
onChanged: (value) { setState(() { if (value == null) { return; } category = value as int; product = null; // 重置产品选中值,避免无效选中 }); },
3. 优化产品下拉的空状态
当未选中分类时,给产品下拉添加提示选项:
items: category == null ? [const DropdownMenuItem(child: Text('请先选择分类'))] : getProductsOptions(),
完整修复后的home.dart代码
class _HomePageState extends ConsumerState<HomePage> { int? category; int? product; List<Map<String, dynamic>> loadProd = []; @override Widget build(BuildContext context) { final themeService = ref.watch(themeServiceProvider); final ancScaffold = Scaffold.maybeOf(context); getProductsOptions() { loadProd = LocalData.products .where((prod) => (prod['categoriesId'] as List<int>).contains(category)) .toList(); return loadProd.map((val) { return DropdownMenuItem( value: val['id'], child: Container(child: Text(val['name']))); }).toList(); } return Scaffold( appBar: AppBar( bottom: themeService.appbarBottom(), elevation: 0, ), body: SingleChildScrollView( child: Column( children: [ Material( child: Container( child: Form( child: Column( children: [ SizedBox( child: DropdownButtonFormField( value: category, isExpanded: true, decoration: const InputDecoration( labelText: 'Categories', ), items: LocalData.categories.map((cat) { return DropdownMenuItem( value: cat['id'], child: Container(child: Text(cat['name']))); }).toList(), onChanged: (value) { setState(() { if (value == null) { return; } category = value as int; product = null; // 重置产品选中值 }); }, ), ), SizedBox( child: DropdownButtonFormField( value: product, isExpanded: true, decoration: const InputDecoration( labelText: 'Products', ), items: category == null ? [const DropdownMenuItem(child: Text('请先选择分类'))] : getProductsOptions(), onChanged: (prod) { setState(() { if (prod == null) { return; } product = prod as int; }); }, ), ), ], ), ), ), ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者Epi94
相关产品推荐
相关产品推荐

