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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:44:59