Flutter获取TextField与DropdownButton值并POST提交表单到API
Flutter 多类型表单字段收集与API提交实现
你可以按照以下步骤完成需求:
- 第一步:初始化状态管理对象
首先在对应页面的State类中,声明表单全局Key、文本输入控制器、下拉选中值存储变量,用于统一管理所有表单状态:
// 表单全局Key,用于触发表单校验、管理表单状态 final _formKey = GlobalKey<FormState>(); // 所有文本输入框对应的控制器,用于直接获取输入内容 final TextEditingController titleController = TextEditingController(); final TextEditingController companyController = TextEditingController(); final TextEditingController locationController = TextEditingController(); final TextEditingController descController = TextEditingController(); final TextEditingController salaryController = TextEditingController(); // 存储两个下拉组件的选中值 String? selectedCommonDropdown; // 对应普通DropdownButton的选中值 String? selectedCategory; // 对应DropdownSearch的选中分类值
- 第二步:补全原有表单组件的缺失参数
- 给Form组件绑定上面声明的
_formKey:Form(key: _formKey) - 给原来没有绑定控制器的Location、Description、Salary三个TextFormField补上controller参数,分别绑定对应的locationController、descController、salaryController
- 修改两个下拉组件的onChanged回调,选中时同步更新状态变量:
- 给Form组件绑定上面声明的
// 普通DropdownButton的onChanged逻辑 onChanged: (String? val) { setState(() { selectedCommonDropdown = val; }); }, // DropdownSearch组件补全onChanged和selectedItem参数 DropdownSearch<String>( mode: Mode.MENU, showSearchBox: false, showClearButton: true, items: const ["Aviation", "Arts", "Business"], // 选中值回显 selectedItem: selectedCategory, dropdownSearchDecoration: const InputDecoration( labelText: "Category", hintText: "Select Job Category", ), // 选中时更新状态 onChanged: (String? val) { setState(() { selectedCategory = val; }); }, ),
- 第三步:实现Add按钮的提交逻辑
在按钮的onPressed回调中,按顺序完成表单校验、字段收集、接口提交操作:
onPressed: () async { // 触发表单校验,校验不通过直接终止流程 if (_formKey.currentState?.validate() != true) return; // 校验下拉选项是否已选择,可根据业务需求调整提示 if (selectedCommonDropdown == null || selectedCategory == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("请完成所有下拉选项选择")), ); return; } // 收集所有字段值,按照API要求的参数名组装提交数据 final Map<String, dynamic> submitData = { "job_title": titleController.text.trim(), "company": companyController.text.trim(), "type": selectedCommonDropdown, // 替换为接口实际要求的参数名 "category": selectedCategory, "location": locationController.text.trim(), "description": descController.text.trim(), "salary": salaryController.text.trim(), }; // 调用接口提交数据,替换为你项目实际的网络请求逻辑 try { // 示例:替换为你的接口请求代码 // await dio.post("/job/add", data: submitData); // 提交成功后的逻辑:提示、清空表单、跳转等 ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("职位添加成功")), ); // 可选:提交成功后重置表单 _formKey.currentState?.reset(); for (final controller in [titleController, companyController, locationController, descController, salaryController]) { controller.clear(); } setState(() { selectedCommonDropdown = null; selectedCategory = null; }); } catch (e) { // 提交失败的错误提示 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("提交失败:${e.toString()}")), ); } },
- 第四步:补充内存泄漏处理和校验规则
- 在页面的dispose生命周期中释放所有TextEditingController,避免内存泄漏:
@override void dispose() { titleController.dispose(); companyController.dispose(); locationController.dispose(); descController.dispose(); salaryController.dispose(); super.dispose(); }
- 如果需要给文本输入框加必填校验,给TextFormField添加validator属性即可,示例:
TextFormField( controller: titleController, decoration: const InputDecoration(hintText: 'Job Title'), validator: (value) { if (value?.trim().isEmpty == true) { return "请输入职位名称"; } return null; }, ),
注意:组装submitData的时候,Map的key需要和后端API文档要求的参数名完全一致,否则会提交失败。
内容的提问来源于stack exchange,提问作者Zemichael Muluken
相关产品推荐
相关产品推荐

