在复杂的v-for循环中的Vue组件中预选无线电输入

时间:2019-01-25 17:20:52

标签: javascript vue.js vuejs2

我有一个Vue组件,该组件可以处理多种表单,可以从Gravity表单API检索数据并向其中提交数据。除了预选无线电输入的默认值(以切换形式显示)之外,其他所有功能都可以正常运行。

以下是该组件的简化版本:

<template>
    <form :id="gf" ref="form">
        <div
            v-for="field in fields"
            :key="field.id"
            :id="`field_${field.id}`"
            :class="`field field__${field.type}`"
        >
            <div v-if="field.type == 'radio'">
                <div v-for="(choice, index) in field.choices" :key="choice.value">
                    <input
                        type="radio"
                        :id="`gf_${index}_${field.id}`"
                        :name="`input_${field.id}`"
                        :value="choice.value"
                        v-model="entries[`input_${field.id}`]"

                        // insert way of checking input with isSelected == true here
                    >
                    <label :for="`gf_${index}_${field.id}`">{{ choice.text }}</label>
                </div>
            </div>
        </div>
    </form>
</template>

<script>
export default {
    props: {
        formId: {
            type: String,
            default: '',
        },
        formName: {
            type: String,
            default: '',
        },
    },

    data() {
        return {
            fields: '',
            form: '',
            entries: {},
        }
    },

    mounted: function() {
        this.getForm()
    },

    methods: {
        getForm() {
            const vm = this
            axios
                .post('path/to/gravity/forms/api', {
                    id: vm.formId,
                })
                .then(result => {
                    vm.form = result.data
                    vm.fields = result.data.fields
                })
                .catch(err => {
                    console.log(err)
                })
        },

    },
}
</script>

请注意,这些值以正确的方式提交给表单,但仅在单击时才提交。我需要找到一种基于从api检索的数据自动检查输入的方法。

API为每个无线电输入返回一个简单的数组,默认输入(按重力形式定义)如下:

isSelected: true
text: "Email"
value: "Email"

注意:我已经阅读了关于Stack Overflow相关问题的许多答案,但是该解决方案总是涉及将值硬编码到数据中,这不是一种选择。另外,还必须以上述格式添加条目,以使API能够理解提交(此代码不相关,因此未包括在内)。

感谢所有建议。

2 个答案:

答案 0 :(得分:0)

借助Daniel和Roy J的指针,我能够通过添加一种方法来遍历传入字段并相应地更新entrys对象,从而合理地解决此问题。

   getForm() {
        const vm = this
        axios
            .post('/path/to/gf/api', {
                id: vm.formId,
            })
            .then(result => {
                vm.form = result.data
                vm.fields = result.data.fields
                vm.getRadios()
            })
            .catch(err => {
                console.log(err)
            })
    },
    getRadios() {
        let radios = this.fields.filter(field => field.type == 'radio')
        radios.forEach(radio => {
            let selected = radio.choices.find(
                choice => choice.isSelected == true
            )
            this.entries[`input_${radio.id}`] = selected.value
        })
    },

我还添加了

 :checked="choice.isSelected"

在模板上,以及以前的v模型。

答案 1 :(得分:-1)

如果您没有将entries用于其他任何用途,则完全不需要。您不需要v-model,只需要设置checked,这非常简单:

:checked="choice.isSelected"

new Vue({
  el: '#app',
  data: {
    fields: []
  },
  methods: {
    fetchData() {
      setTimeout(() => {
        this.fields = [
          {
            id: 1,
            type: 'radio',
            choices: [
              {
                isSelected: false,
                value: 1,
                text: 'one'
              },
              {
                isSelected: true,
                value: 2,
                text: 'two'
              }
            ]
          },
          {
            id: 2,
            type: 'radio',
            choices: [
              {
                isSelected: true,
                value: 1,
                text: 'three'
              },
              {
                isSelected: false,
                value: 2,
                text: 'four'
              }
            ]
          },
        ];
      }, 500);
    }
  },
  created() {
    this.fetchData();
  }
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<form id="app">
  <div v-for="field in fields" :key="field.id" :class="`field field__${field.type}`">
    <div v-for="(choice, index) in field.choices" :key="choice.value">
      <input type="radio" :id="`gf_${index}_${field.id}`" :name="`input_${field.id}`" :value="choice.value" :checked="choice.isSelected">
      <label :for="`gf_${index}_${field.id}`">{{ choice.text }}</label>
    </div>
  </div>
</form>