在 Vue 中创建带有条件问题的动态表单

Posted

技术标签:

【中文标题】在 Vue 中创建带有条件问题的动态表单【英文标题】:Create dynamic form in Vue with conditional questions 【发布时间】:2018-07-27 08:06:53 【问题描述】:

但是,我想动态创建一个带有条件字段的表单。形式的定义在对象 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>

我只想在年龄 > 30 岁时显示“条件问题”。

在对象 Q 中,我无法访问 this.Q(因为它还不存在)。 v-on:change="onChange" 可以工作,但这违背了 Vue 的全部意义

我没有绑定到对象的这个结构,但是它将使用 AJAX 获得...

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

【问题讨论】:

为什么不改变你的结构来使用“key:value”对呢?您的对象数组包含 2 个非常不同的对象,但您的结构设置为将它们视为相同类型。 @Stephan-v 是的,这似乎有效!谢谢! 【参考方案1】:

我通过在模板中的第二个 div 上使用“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)
    ,

【讨论】:

代码的唯一“问题”是Q[0] 是硬编码的。我使用了您的方法,将条件放入方法中并添加了更多条件。现在似乎一切正常!【参考方案2】:

正如@Stephan-v 所说,我将对象更改为 key:value 对象,而不是数组。从@Radovan-Šurlák 的帖子中可以看出,不需要观察者。请注意,计算对象只能在“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>

【讨论】:

以上是关于在 Vue 中创建带有条件问题的动态表单的主要内容,如果未能解决你的问题,请参考以下文章

我想创建一个带有用户个人资料名称自动输入的联系表格(动态文本)

多字段引导动态表单

如何动态添加带有引导表单元素的 div?

在 VBA Access 中动态填充其他子表单的子表单

使用python在zeppelin中动态选择表单

我想在更改时保存表单,并使用 laravel 和 Jquery 创建一个动态表单