使用条件问题在 Vue 中创建动态表单

Create dynamic form in Vue with conditional questions

但是,我想动态创建一个带有条件字段的表单。表单的定义在对象 Q 中。 下面的例子是一个 Vue 组件,使用 bootstrap-vue.

<template>
    <div>
        <div v-for="q of Q">
            <br/>
            <template v-if="q.type == 'input'">
                {{ q.question }}
                <em v-if="q.comment"><br />{{ q.comment }}</em>
                <b-form-input v-model="q.value" :type="q.subtype" :placeholder="q.placeholder"></b-form-input>
                Value: {{ q.value }}
            </template>

            <template v-if="q.type == 'radio'">
                {{ q.question }}
                <em v-if="q.comment"><br />{{ q.comment }}</em>
                <b-form-group>
                    <b-form-radio-group buttons
                                        stacked
                                        v-model="q.value"
                                        :options="q.options"/>
                </b-form-group>

                Value: {{ q.value }}
            </template>

        </div>
    </div>
</template>

<script>
    export default {
        name: 'Questionnaire',
        data() {
            return {
                locale: 'en',
                Q: [
                    {
                        name: 'age',
                        value: null,
                        question: 'How old are you?',
                        placeholder: 'Your age...',
                        comment: 'years since you were born',
                        type: 'input',
                        subtype: 'number',
                        range: [18, 99],
                    },
                    {
                        name: 'cq',
                        value: null,
                        question: 'Conditional Question?',
                        type: 'radio',
                        options: [
                            {text: 'Yes', value: '0'},
                            {text: 'No', value: '1'},
                        ],
                        if: [{object: 'age', largerthan: 30}],
                    },
                ]
            };
        },
        methods: {
            onChange: function(){
                alert('test');
            },
        },
    }
</script>

我想显示 "Conditional Question" 只有当年龄 > 30 时。

我不受此对象结构的约束,但是它将使用 AJAX...

获得

问题:有没有办法观看this.Q[0].value?或者只有当第一个问题具有特定值时才能使第二个问题可用的其他方法?

如@Stephan-v 所说,我将对象更改为 key:value 对象,而不是数组。从@Radovan-Šurlák 的 post 中可以看出,不需要观察者。请注意,计算对象只能在 "beforeCreate" 和方法中创建,变量尚未初始化。将变量从 beforeCreate 传递给对象似乎相当困难。

因此使用@Radovan-Šurlák 作为基础,并稍微改进它会导致:

<template>
    <div>
        <div v-for="(q, name) of Q" v-if="doShow( name )">
            <br/>
            <template v-if="q.type == 'input'">
                <b>{{ q.question }}</b>
                <em v-if="q.comment"><br/>{{ q.comment }}</em>
                <b-form-input v-model="q.value" :type="q.subtype" :placeholder="q.placeholder"></b-form-input>
            </template>

            <template v-if="q.type == 'radio'">
                <b>{{ q.question }}</b>
                <em v-if="q.comment"><br/>{{ q.comment }}</em>
                <b-form-group>
                    <b-form-radio-group buttons
                                        stacked
                                        v-model="q.value"
                                        :options="q.options"/>
                </b-form-group>
            </template>

        </div>
    </div>
</template>

<script>
    export default {
        name: 'Questionnaire',
        data() {
            return {
                locale: 'en',
                Q: {
                    age: {
                        value: null,
                        question: 'How old are you?',
                        placeholder: 'Your age...',
                        comment: 'years since you were born',
                        type: 'input',
                        subtype: 'number',
                        range: [18, 99],
                    },
                    cq: {
                        value: null,
                        question: 'Conditional Question?',
                        type: 'radio',
                        options: [
                            {text: 'Yes', value: '0'},
                            {text: 'No', value: '1'},
                        ],
                        if: [{object: 'age', largerthan: 30, smallerthan: 35, equals: 31, notequal: 32}],
                    },
                },
            };
        },
        methods: {
            doShow: function( field ) {
                for( var obj in this.Q[ field ].if )
                {
                    var ifObj = this.Q[ field ].if[ obj ];
                    if( ifObj.equals !== undefined && this.Q[ ifObj.object ].value != ifObj.equals )
                        return false;
                    if( ifObj.notequal !== undefined && this.Q[ ifObj.object ].value == ifObj.notequal )
                        return false;
                    if( ifObj.largerthan !== undefined && this.Q[ ifObj.object ].value <= ifObj.largerthan )
                        return false;
                    if( ifObj.smallerthan !== undefined && this.Q[ ifObj.object ].value >= ifObj.smallerthan )
                        return false;
                }
                return true;
            },
            submit: function () {
                console.log('Submit form, send back data via Axios')
            },
        },
        mounted() {
            // Axios call
        }
    }
</script>

我通过在您的模板中 div 的第 2 个 "v-if" 指令成功创建了效果。

然后我用空数组初始化"Q"数组,并在"created()"生命周期钩子中通过setTimeout模拟AJAX请求。

<template>
  <div>
    <div v-if="!(q.if) || Q[0].value > q.if[0].largerthan" v-for="q of Q">
        <br/>
        <template v-if="q.type == 'input'">
            {{ q.question }}
            <em v-if="q.comment"><br />{{ q.comment }}</em>
            <b-form-input v-model="q.value" :type="q.subtype" :placeholder="q.placeholder"></b-form-input>
            Value: {{ q.value }}
        </template>

        <template v-if="q.type == 'radio'">
            {{ q.question }}
            <em v-if="q.comment"><br />{{ q.comment }}</em>
            <b-form-group>
                <b-form-radio-group buttons
                                    stacked
                                    v-model="q.value"
                                    :options="q.options"/>
            </b-form-group>

            Value: {{ q.value }}
        </template>

    </div>
  </div>
</template>

<script>
  export default {
    name: 'Questionnaire',
    data() {
        return {
            locale: 'en',
            Q: [],
        };
    },
    created() {
      setTimeout( _ => this.Q = [
                {
                    name: 'age',
                    value: null,
                    question: 'How old are you?',
                    placeholder: 'Your age...',
                    comment: 'years since you were born',
                    type: 'input',
                    subtype: 'number',
                    range: [18, 99],
                },
                {
                    name: 'cq',
                    value: null,
                    question: 'Conditional Question?',
                    type: 'radio',
                    options: [
                        {text: 'Yes', value: '0'},
                        {text: 'No', value: '1'},
                    ],
                    if: [{object: 'age', largerthan: 30}],
                },
                {
                    name: 'age',
                    value: null,
                    question: 'How old are you?',
                    placeholder: 'Your age...',
                    comment: 'years since you were born',
                    type: 'input',
                    subtype: 'number',
                    range: [18, 99],
                },
         ], 500)
    },
}