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

如何构建返回Map列表的自定义FormBuilderField?

实现带自定义FormBuilderField的采购订单数量提交列表组件

需求:从后端获取数据列表,让用户为每条数据提交对应交付数量(类似采购订单报价后的数量选择场景)。现有FormListCard组件无法集成自定义FormBuilderField,以下是解决思路及重构方案:

原组件问题分析

原FormListCard硬编码使用KTextField作为输入组件,无法灵活替换为FormBuilder生态下的表单字段(如FormBuilderTextField、FormBuilderDropdown等),导致无法纳入表单统一管理。

重构思路与实现

1. 重构组件参数,支持自定义表单字段

将固定的KTextField参数替换为可定制的表单字段构建函数,同时增加表单字段名参数,确保每个列表项的字段能被FormBuilder识别。

2. 修改组件内部逻辑,适配FormBuilder规范

在组件内部优先使用外部传入的自定义表单字段,若未传入则默认创建数字输入类型的FormBuilderTextField,满足数量输入的基础需求。

重构后的代码示例

class FormListCard extends StatelessWidget {
  final String title;
  final String subTitle;
  final String fieldName; // 唯一表单字段名,用于FormBuilder关联数据
  final Widget Function(String fieldName)? customField; // 自定义FormBuilderField构建函数

  FormListCard({
    required this.title,
    required this.subTitle,
    required this.fieldName,
    this.customField,
  });

  @override
  Widget build(BuildContext context) {
    bool isLandScape = MediaQuery.of(context).orientation == Orientation.landscape;
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const Divider(),
        Row(
          children: [
            Text(
              title,
              style: TextStyle(
                fontSize: isLandScape ? 18.sp : 32.sp,
                fontWeight: FontWeight.w600,
              ),
            ),
            const Spacer(),
            textInput(isLandScape),
            SizedBox(width: 20.w),
            Text(
              subTitle,
              style: TextStyle(
                fontSize: isLandScape ? 18.sp : 32.sp,
                fontWeight: FontWeight.w600,
              ),
            )
          ],
        )
      ],
    );
  }

  Widget textInput(bool isLandScape) {
    // 优先使用自定义字段,否则默认创建数字输入框
    final Widget field = customField?.call(fieldName) ?? 
        FormBuilderTextField(
          name: fieldName,
          keyboardType: TextInputType.number,
          decoration: const InputDecoration(hintText: "输入数量"),
          validator: (value) {
            if (value == null || value.isEmpty) return "请输入数量";
            if (int.tryParse(value) == null) return "请输入有效数字";
            return null;
          },
        );

    return SizedBox(
      width: isLandScape ? 150.w : 300.w,
      height: isLandScape ? 150.h : 80.h,
      child: field,
    );
  }
}

使用示例

将组件包裹在FormBuilder内,为每条后端数据生成唯一的字段名,同时可自定义表单字段类型:

// 假设后端返回的订单数据结构
class OrderItem {
  final String id;
  final String name;
  final String unit;
  final int defaultQuantity;

  OrderItem({required this.id, required this.name, required this.unit, required this.defaultQuantity});
}

// 表单使用示例
final _formKey = GlobalKey<FormBuilderState>();
List<OrderItem> orderItems = []; // 从后端获取的订单列表

@override
Widget build(BuildContext context) {
  return FormBuilder(
    key: _formKey,
    child: Column(
      children: orderItems.map((item) {
        return FormListCard(
          title: item.name,
          subTitle: item.unit,
          fieldName: "quantity_${item.id}", // 唯一字段名,关联订单ID
          // 自定义FormBuilderTextField,可根据需求替换为其他组件
          customField: (fieldName) => FormBuilderTextField(
            name: fieldName,
            keyboardType: TextInputType.number,
            initialValue: item.defaultQuantity.toString(),
            decoration: const InputDecoration(
              labelText: "交付数量",
              border: OutlineInputBorder(),
            ),
          ),
        );
      }).toList(),
    ),
  );
}

// 提交表单时获取所有数量数据
void submitForm() {
  if (_formKey.currentState!.validate()) {
    _formKey.currentState!.save();
    final formData = _formKey.currentState!.value;
    // 解析formData,根据fieldName匹配对应订单的数量
    for (var item in orderItems) {
      final quantity = int.parse(formData["quantity_${item.id}"] ?? "0");
      // 处理每条订单的数量数据
    }
  }
}

关键注意事项

  • 所有FormListCard必须包裹在FormBuilder组件内,才能实现表单状态统一管理。
  • 每个列表项的fieldName必须唯一,建议结合后端数据的唯一标识(如ID)生成,避免提交时数据混淆。
  • 自定义字段时,只需传入符合FormBuilderField规范的组件(需设置正确的name属性),即可无缝集成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:31:05