当前位置: 首页 > 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 组件,特别是在字段数量和内容不确定的情况下。

http://www.dtcms.com/a/23651.html

相关文章:

  • 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发票浏览器,实现按发票样式显示
  • Java 设计模式之命令模式
  • 分布式 IO 模块:食品罐装产线自动化与高效运行的推手
  • 个人搭建CDN加速服务 特网科技
  • 解决vue-awesome-swiper 4.x + swiper 5.x 分页pagination配置不生效问题
  • Dify本地安装
  • 开源在线考试系统开源在线考试系统:支持数学公式的前后端分离解决方案
  • 动态内存管理
  • 栈与队列(C语言版)
  • 数据分析简介及其常用指标与方法
  • 毕业设计—基于Spring Boot的社区居民健康管理平台的设计与实现