如何从组件输入中捕获数据?

问题描述 投票:0回答:1

我有一个名为 NewIngredientInput 的组件,我在新菜谱页面上使用它。该组件由 3 个输入组成:amountunitname。我正在使用 Nuxt 3,使用 Formkit 以及消费和外部 API 处理表单。

当我将数据从表单发送到端点进行发布时,它仅捕获来自输入amount的信息,对于其他两个输入(unitname),它发送一个空字符串,因此 POST 请求成功。我指定对于不在 NewIngredientInput 组件内的其他输入,信息已成功捕获。

这是我的新菜谱页面代码:

<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">
          <FormKit
            v-model="recipeData.name"
            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
              v-model="row.amount"
              v-model:unit_measure="row.unit_measure"
              v-model:name="row.name"
              :showRemoveButton="index > 0"
              @removeRow="removeRow(index)"
            />
            <button @click="addRow" class="add">+</button>
          </div>
          <FormKit
            v-model="recipeData.description"
            type="textarea"
            rows="10"
            name="description"
            label="Instrucciones"
            placeholder="Escribe oraciones o párrafos."
            validation="required"
          />
          <div class="triple">
            <FormKit
              v-model="recipeData.region"
              type="text"
              name="region"
              label="Región"
              validation="required"
            />
            <FormKit
              v-model="recipeData.keywords"
              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" />
        </FormKit>
      </div>
    </div>
  </div>
</template>

<script>
import NewIngredientInput from "../components/NewIngredientInput.vue";
import axios from "axios";

export default {
  components: {
    NewIngredientInput,
  },
  data() {
    return {
      inputRows: [{ amount: "", unit_measure: "", name: "" }],
      recipeData: {
        name: "",
        description: "",
        region: "",
        keywords: "",
      },
    };
  },
  methods: {
    addRow() {
      this.inputRows.push({ amount: "", unit_measure: "", name: "" });
    },
    removeRow(index) {
      this.inputRows.splice(index, 1);
    },

    async createRecipe() {
      try {
        const photoInput = document.querySelector('input[name="photo"]');

        if (photoInput && photoInput.files && photoInput.files.length > 0) {
          const photoForm = new FormData();
          photoForm.append("photo", photoInput.files[0]);

          const imageResponse = await axios.post(
            "API endpoint for upload newImage",
            photoForm,
            {
              headers: {
                "Content-Type": `multipart/form-data; boundary=${photoForm._boundary}`,
              },
            }
          );

          const ingredient = this.inputRows.map((row) => {
            return {
              amount: row.amount.amount,
              unit: row.unit_measure,
              name: row.name,
            };
          });

          const recipeForm = {
            name: this.recipeData.name,
            ingredients: ingredient,
            description: this.recipeData.description,
            region: this.recipeData.region,
            keywords: this.recipeData.keywords,
            photo: imageResponse.data,
          };

          console.log(recipeForm);

          const recipeResponse = await axios.post(
            "API endpoint for upload the entire recipe",
            recipeForm
          );

          console.log("Receta creada exitosamente: ", recipeResponse.data);
        } else {
          console.error("No se seleccionó ninguna imagen");
        }
      } catch (error) {
        console.error(error);
      }
    },
  },
};
</script>

如果我不在 NewIngredientInput 上使用

v-model:unit_measure="row.unit_measure"
v-model:name="row.name"
,当我为新成分添加一行时,它会继承旧成分的信息并被覆盖,从而产生单行而不是包含多种成分的数组.

我还附上了 NewIngredientInput 组件的脚本以获取更多上下文:

<template>
  <FormKit type="form" name="ingredients">
    <div class="newIngredient">
      <FormKit
        v-model="ingredient.amount"
        type="number"
        name="amount"
        id="amount"
        label="Cantidad"
        min="1"
        validation="required"
      />
      <FormKit
        v-model="ingredient.unit_measure"
        type="text"
        name="unit"
        id="unit"
        label="Unidad"
        validation="required"
      />
      <div class="ingredient">
        <FormKit
          v-model="ingredient.name"
          type="text"
          name="name"
          id="name"
          label="Ingrediente"
          validation="required"
        />
      </div>
      <button class="remove" @click="removeRow" v-show="showRemoveButton">
        -
      </button>
    </div>
  </FormKit>
</template>

<script>
export default {
  props: {
    showRemoveButton: {
      type: Boolean,
      default: false,
    },

    // Pass the ingredient object as a prop
    ingredientValue: Object,
  },
  data() {
    return {
      ingredient: { amount: "", unit_measure: "", name: "" },
    };
  },
  watch: {
    // When the prop value (ingredient object) changes, update the local ingredient data
    ingredientValue: {
      handler(newValue) {
        this.ingredient.amount = newValue.amount;
        this.ingredient.unit_measure = newValue.unit_measure;
        this.ingredient.name = newValue.name;
      },
      deep: true,
    },
  },
  methods: {
    removeRow() {
      this.$emit("removeRow");
    },
  },
};
</script>
vue.js nuxt.js vuejs3 nuxt3 formkit
1个回答
0
投票

如果我正确理解问题,问题在于您如何在 NewIngredientInput 组件上使用 v-model。它应该绑定到单个模型,但您要绑定到多个模型(金额、单位度量、名称)。这是简化的解决方案:

NewIngredientInput
页面中更改您的
newrecipe
,如下所示:

<NewIngredientInput
  :value="row"
  :showRemoveButton="index > 0"
  @removeRow="removeRow(index)"
/>

并且:

<template>
  <!-- Your existing template code -->
</template>

<script>
export default {
  props: {
    showRemoveButton: Boolean,
    value: { type: Object, required: true },
  },
  data() {
    return { ingredient: { ...this.value } };
  },
  watch: {
    ingredient: {
      handler() { this.$emit('update', this.ingredient); },
      deep: true
    },
    value: {
      handler(newValue) { this.ingredient = { ...newValue }; },
      deep: true
    }
  },
  methods: {
    removeRow() { this.$emit("removeRow"); },
  },
};
</script>

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.