在 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 中创建带有条件问题的动态表单的主要内容,如果未能解决你的问题,请参考以下文章