当前位置: 首页 > news >正文

Flutter:动态表单(在不确定字段的情况下,生成动态表单)

关于数据模型:模型就是一种规范约束,便于维护管理,在不确定表单内会出现什么数据时,就没有模型一说。
这时就要用到动态表单(根据接口返回的字段,生成动态表单)

1、观察数据格式,定义模型

modelData:[
	{
		id:1,
		name:'模型一',
		ctaVal:{
  			"first_usdt": {"val": "10", "title": "首仓金额", "unit": "usdt", "read": "0" },
		}
	},
	{
		id:2,
		name:'模型二',
		ctaVal:{
		    "min_profit": {"val": "2", "title": "最小收益率", "unit": "%", "read": "1"}
		}
	}
]


上边自定义的数据格式,已知id和name为固定格式,
ctaVal内的数据不确定具体会返回什么信息,
接口从别的地方抓取的数据,不确定具体字段,
需要动态展示的数据定义:`final Map<String, dynamic> ctaVal;`

class DynamicFormModel {
	int? id;
	String? name;
	final Map<String, dynamic> ctaVal;

  DynamicFormModel ({
    required this.id,
    required this.name,
    required this.ctaVal,
  });

	factory DynamicFormModel .fromJson(Map<String, dynamic> json) {
		return StrategyListModel(
			id: json['id'] as int?,
			name: json['name'] as String?,
			ctaVal: json['ctaVal'] ?? {},
		);
	}

	Map<String, dynamic> toJson() => {
				'id': id,
				'name': name,
				'ctaVal': ctaVal,
			};
}

2、接口处理,请求数据,

// 模型列表
List<DynamicFormModel> modelList = [];
// 当前选中的模型id
int modelId = 0;
// 当前选中的模型
DynamicFormModel? selectedModel;
// 动态表单控制器
final Map<String, TextEditingController> fieldControllers = {};

@override
  void onReady() {
  super.onReady();
  // 获取模型列表、默认模型为第一条数据
  modelList = modelData.map((e) => DynamicFormModel .fromJson(e)).toList();
  if (modelList.isNotEmpty) {
    selectedModel = modelList.first;
    modelController.text = selectedModel?.name ?? '';
    modelId = selectedModel?.id ?? 0;
  }
  update(["strategy_add"]);
}

@override
void onClose() {
  super.onClose();
  // 释放所有控制器
  fieldControllers.forEach((key, controller) {
    controller.dispose();
  });
}

void submit() async{
  // 获取每个字段的值
  for (var entry in fieldControllers.entries) {
    if (entry.value.text.isEmpty) {
      Loading.toast('请输入完整内容');
      return;
    }
  }

  // 收集动态表单内的数据,key=键名(first_usdt)
  Map<String, String> data = {};
  fieldControllers.forEach((key, controller) {
    data[key] = controller.text;
    print('$key,${controller.text}');
  });
  // 如果需要自定义字段 
  data['remark'] = remarkController.text;
  // 转换为 JSON
  String jsonData = jsonEncode(data);
  print('jsonData = $jsonData');
}

3、动态渲染表单页面

// 表单
Widget _buildForm() {
  return GetBuilder<StrategyAddController>(
    id: "strategy_model",
    builder: (_) {
      return <Widget>[
        controller.selectedModel == null
            ? const Center(child: Text('请选择一个模型'))
            : <Widget>[
                ...controller.selectedModel!.ctaVal.entries.map((item) {
                  // 获取或创建控制器
                  final controllerKey = item.key;
                  if (!controller.fieldControllers.containsKey(controllerKey)) {
                    controller.fieldControllers[controllerKey] = TextEditingController(text: item.value['val']);
                  }
                  final fieldController = controller.fieldControllers[controllerKey];
                  return <Widget>[
                    InputWidget(
                      prefix: TextWidget.body(
                        item.value['title'],
                      ),
                      placeholder: item.value['read'] == '1'
                          ? ""
                          : '请输入${item.value['title']}',
                      controller:fieldController,
                      readOnly: item.value['read'] == '1' ? true : false,
                    ).expanded(),
                    TextWidget.body(
                      item.value['unit'],
                    ),
                  ].toRow(crossAxisAlignment: CrossAxisAlignment.center).opacity(item.value['read'] == '1' ? 0.5 : 1);
                }),

              ].toColumn(crossAxisAlignment: CrossAxisAlignment.start)
      ].toColumn();
    },
  );
}

...controller.selectedModel!.ctaVal.entries.map((item) => ...) 会遍历 ctaVal 中的每个条目,并将其映射为一个新的 Widget 列表。
每个 item 是一个 MapEntry,可以通过 item.keyitem.value 访问键和值。
这种方式非常适合动态生成 UI 组件,特别是在字段数量和内容不确定的情况下。

相关文章:

  • Linux 进程控制(进程创建,进程等待)
  • 手机功耗BugReport字段含义介绍
  • 软件考研,选择华科还是科软?
  • Java与C语言中取模运算符%的区别对比
  • 如何使用 Ollama 和 Docker 设置 DeepSeek
  • Query String 传递 json 对象参数、map参数
  • 【设计模式】【结构型模式】组合模式(Composite)
  • 根据deepseek模型微调训练自动驾驶模型及数据集的思路
  • 智能猫眼实现流程图
  • matlab数据处理:创建网络数据
  • 接口测试工具:Postman
  • 【记忆化搜索】最长递增子序列
  • Nginx内存池源代码剖析----ngx_create_pool函数
  • AI 新动态:技术突破与应用拓展
  • 【万字详细教程】Linux to go——装在移动硬盘里的Linux系统(Ubuntu22.04)制作流程;一口气解决系统安装引导文件迁移显卡驱动安装等问题
  • 机器学习实战(4):逻辑回归——分类问题的基础
  • 【git-hub项目:YOLOs-CPP】本地实现03:跑自己的实例分割模型
  • Kafka
  • 训练数据为什么需要Shuffle
  • 如何使用qt开发一个xml发票浏览器,实现按发票样式显示
  • 2人恶意传播刘国梁谣言被处罚,媒体:以法律利剑劈谣斩邪,加快推进依法治体
  • 莫高义在第四届中国新闻发言人论坛开幕式上的致辞
  • 小米汽车回应部分SU7前保险杠形变
  • 当智慧农场遇见绿色工厂:百事如何用科技留住春天的味道?
  • 大陆非遗项目打铁花、英歌舞将在台演出
  • 小米汽车机盖门陷谈判僵局,车主代表称小米表示“退订会造成崩塌”