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

Flutter动态表单功能异常,求简易实现方案

Flutter 动态可添加项表单实现示例

核心实现思路

用列表存储每组表单的数据源,通过setState更新列表长度来动态添加/移除表单项,每组表单对应一个数据模型,绑定输入控件的值。

完整代码示例

import 'package:flutter/material.dart';

// 定义表单项的数据模型
class FormItem {
  String phone;
  String email;
  String selectedOption;

  FormItem({
    this.phone = '',
    this.email = '',
    this.selectedOption = '',
  });
}

class DynamicFormPage extends StatefulWidget {
  const DynamicFormPage({super.key});

  @override
  State<DynamicFormPage> createState() => _DynamicFormPageState();
}

class _DynamicFormPageState extends State<DynamicFormPage> {
  // 存储所有表单项的列表,初始化时默认添加一组
  final List<FormItem> _formItems = [FormItem()];
  // 表单全局key,用于验证和提交
  final _formKey = GlobalKey<FormState>();

  // 添加新的表单项
  void _addFormItem() {
    setState(() {
      _formItems.add(FormItem());
    });
  }

  // 移除指定索引的表单项(至少保留一组)
  void _removeFormItem(int index) {
    if (_formItems.length > 1) {
      setState(() {
        _formItems.removeAt(index);
      });
    }
  }

  // 提交表单,处理数据
  void _submitForm() {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();
      // 这里可以处理收集到的表单数据,比如打印或上传
      for (var item in _formItems) {
        print('手机号: ${item.phone}, 邮箱: ${item.email}, 选项: ${item.selectedOption}');
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('动态表单')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              // 遍历生成所有表单项
              ..._formItems.asMap().entries.map((entry) {
                int index = entry.key;
                FormItem item = entry.value;
                return Card(
                  margin: const EdgeInsets.only(bottom: 16),
                  child: Padding(
                    padding: const EdgeInsets.all(16),
                    child: Column(
                      children: [
                        // 手机号输入框
                        TextFormField(
                          initialValue: item.phone,
                          keyboardType: TextInputType.phone,
                          decoration: const InputDecoration(labelText: '手机号'),
                          validator: (value) {
                            if (value == null || value.isEmpty) {
                              return '请输入手机号';
                            }
                            // 可添加手机号格式验证
                            return null;
                          },
                          onSaved: (value) {
                            item.phone = value!;
                          },
                        ),
                        const SizedBox(height: 12),
                        // 邮箱输入框
                        TextFormField(
                          initialValue: item.email,
                          keyboardType: TextInputType.emailAddress,
                          decoration: const InputDecoration(labelText: '邮箱'),
                          validator: (value) {
                            if (value == null || value.isEmpty) {
                              return '请输入邮箱';
                            }
                            // 可添加邮箱格式验证
                            if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
                              return '请输入正确的邮箱格式';
                            }
                            return null;
                          },
                          onSaved: (value) {
                            item.email = value!;
                          },
                        ),
                        const SizedBox(height: 12),
                        // 下拉选择框
                        DropdownButtonFormField<String>(
                          value: item.selectedOption.isNotEmpty ? item.selectedOption : null,
                          decoration: const InputDecoration(labelText: '选择选项'),
                          items: const [
                            DropdownMenuItem(value: 'option1', child: Text('选项1')),
                            DropdownMenuItem(value: 'option2', child: Text('选项2')),
                            DropdownMenuItem(value: 'option3', child: Text('选项3')),
                          ],
                          validator: (value) {
                            if (value == null) {
                              return '请选择一个选项';
                            }
                            return null;
                          },
                          onChanged: (value) {
                            setState(() {
                              item.selectedOption = value!;
                            });
                          },
                          onSaved: (value) {
                            item.selectedOption = value!;
                          },
                        ),
                        const SizedBox(height: 12),
                        // 移除按钮(仅当存在多组时显示)
                        if (_formItems.length > 1)
                          ElevatedButton(
                            onPressed: () => _removeFormItem(index),
                            style: ElevatedButton.styleFrom(backgroundColor: Colors.redAccent),
                            child: const Text('移除该项'),
                          ),
                      ],
                    ),
                  ),
                );
              }).toList(),
              // 添加新项按钮
              ElevatedButton(
                onPressed: _addFormItem,
                child: const Text('添加新的表单项'),
              ),
              const SizedBox(height: 20),
              // 提交按钮
              ElevatedButton(
                onPressed: _submitForm,
                style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
                child: const Text('提交表单'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// 可以在main函数中直接运行测试
void main() {
  runApp(const MaterialApp(home: DynamicFormPage()));
}

关键细节说明

  • 数据模型FormItem:统一管理每组表单的手机号、邮箱和选中选项,确保每组数据独立不干扰。
  • 动态列表管理:通过_formItems列表的增删操作,结合setState触发UI更新,实现表单项的动态添加/移除。
  • 表单验证与保存:使用Form组件和全局_formKey统一管理表单验证,每个输入控件通过validator做校验,onSaved保存输入值到对应FormItem。
  • 交互逻辑:移除按钮仅在表单项数量大于1时显示,避免清空所有表单;添加按钮点击后直接追加新的FormItem到列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:15:43