Nuxt3+FormKit表单问题:如何将配料存入单一数组?
解决FormKit动态配料表单生成数组结构的问题
问题概述
使用Nuxt 3开发应用,通过FormKit处理表单,在newrecipe页面中用NewIngredientInput组件动态添加配料行,需要将所有配料存储为数组格式以符合API要求,但当前表单输出的是form_2、form_8这类独立对象,无法形成期望的数组结构。
期望与当前输出对比
期望的JSON结构
{ "name": "data", "ingredients": [ { "amount": "1", "unit": "data", "name": "data" }, { "amount": "2", "unit": "data", "name": "data" } ], "description": "data", "region": "data", "keywords": "data", "photo": [ { "name": "1.jpg", "file": "[object File]" } ] }
当前错误的JSON结构
{ "name": "data", "form_2": { "amount": "1", "unit": "data", "name": "data" }, "description": "data", "region": "data", "keywords": "data", "photo": [ { "name": "1.jpg", "file": "[object File]" } ], "form_8": { "amount": "2", "unit": "data", "name": "data" } }
修复步骤
1. 修改NewIngredientInput.vue组件
问题根源在于每个配料组件内部嵌套了FormKit type="form",导致FormKit为每个子表单生成独立的键。需要移除内部表单,改用字段名的数组语法绑定到父表单:
<template> <div class="newIngridient"> <FormKit v-model="row.amount" type="number" :name="`ingredients[${index}].amount`" label="Cantidad" validation="required" /> <FormKit v-model="row.unit_measure" type="text" :name="`ingredients[${index}].unit`" label="Unidad" validation="required" /> <div class="ingredient"> <FormKit v-model="row.name" type="text" :name="`ingredients[${index}].name`" label="Ingrediente" validation="required" /> </div> <button class="remove" @click="removeRow" v-show="showRemoveButton"> - </button> </div> </template> <script> export default { props: { showRemoveButton: { type: Boolean, default: false, }, row: { type: Object, required: true, }, index: { type: Number, required: true, }, }, methods: { removeRow() { this.$emit("removeRow"); }, }, }; </script>
2. 修改newrecipe.vue页面
调整组件调用方式,传递row和index,并修正表单提交逻辑:
<template> <div class="container"> <UserMenu /> <SideNavUser /> <div class="new-recipe-container"> <div class="title">Crear Receta</div> <div class="form"> <FormKit type="form" @submit="createRecipe" #default="{ value }"> <FormKit type="text" name="name" label="Título de la Receta" validation="required" /> <div class="new-ingredient" v-for="(row, index) in inputRows" :key="index" > <NewIngredientInput :row="row" :index="index" :showRemoveButton="index > 0" @removeRow="removeRow(index)" /> </div> <button @click="addRow" class="add">+</button> <FormKit type="textarea" rows="10" name="description" label="Instrucciones" placeholder="Escribe oraciones o párrafos." validation="required" /> <div class="triple"> <FormKit type="text" name="region" label="Región" validation="required" /> <FormKit type="text" name="keywords" label="Palabras Clave" placeholder="pollo, ajo, ..." help="Ingresa palabras claves separadas por comas." validation="required" /> <div class="photo"> <FormKit type="file" name="photo" accept=".jpg,.png" label="Imagen" help="Solo puedes incluir imagenes con extensión .jpg o .png" validation="required" /> </div> </div> <FormKit type="submit" label="Crear" /> <pre wrap>{{ value }}</pre> </FormKit> </div> </div> </div> </template> <script> import axios from "axios"; export default { data() { return { inputRows: [{ amount: "", unit_measure: "", name: "" }], }; }, methods: { addRow() { this.inputRows.push({ amount: "", unit_measure: "", name: "" }); }, removeRow(index) { this.inputRows.splice(index, 1); }, async createRecipe({ value }) { const recipeForm = { ...value, ingredients: value.ingredients.map(ing => ({ amount: ing.amount, unit: ing.unit, name: ing.name })) }; try { const photoForm = new FormData(); photoForm.append("photo", value.photo.files[0]); const imageResponse = await axios.post( "API endpoint for photo", photoForm, { headers: { "Content-Type": "multipart/form-data" } } ); recipeForm.photo = imageResponse.data; const recipeResponse = await axios.post( "API endpoint for all the recipe data", recipeForm ); console.log("Receta creada exitosamente: ", recipeResponse.data); } catch (error) { console.error("Error creating recipe:", error.message); } }, }, }; </script>
关键修复点说明
- 移除
NewIngredientInput内部的FormKit type="form",改用ingredients[${index}].field的命名方式,让FormKit识别这是数组字段。 - 调整添加按钮的位置,避免每个配料行重复生成添加按钮。
- 提交表单时直接使用FormKit提供的
value参数,无需手动从inputRows映射,同时为图片上传请求添加正确的Content-Type头。
内容的提问来源于stack exchange,提问作者Aldrin Cuvi
相关产品推荐
相关产品推荐

