JSFiddle - React, Tailwind, and code Playground
by Simon Herteby
HTML
<div id="vue">
<field v-for="(field, index) in inputQuestions"
:key="index"
v-bind="field"
v-model="outputData[field.reference]">
</field>
<pre>{{outputData}}</pre>
</div>
Vue
Vue.component('field', {
props:{
type:{type:String, required:true},
name:{type:String, required:true},
value:{type:[String, Number], required:true},
options:{type:Array, default:() => []},
placeholder:{type:String, default:''}
},
computed:{
model:{
get(){
return this.value
},
set(val){
if(typeof this.value === 'number'){
this.$emit('input', Number(val))
} else {
this.$emit('input', val)
}
}
}
},
template:`
<div>
<label>{{name}}</label>
<textarea v-if="type === 'textarea'" v-model="model" :placeholder="placeholder"/>
<select v-else-if="type === 'select'" v-model="model">
<option disabled style="display:none" :value="undefined">{{placeholder}}</option>
<option v-for="option in options" :value="option">{{option}}</option>
</select>
<template v-else-if="type === 'radio'">
<div v-for="option in options">
<input type="radio" v-model="model" :value="option">
<label>{{option}}</label>
</div>
</template>
<input v-else :type="type" v-model="model" :placeholder="placeholder">
</div>
`
})
new Vue({
el:'#vue',
data(){
return {
inputQuestions: [
{ name: 'first name', type: 'text', reference: 'firstname'},
{ name: 'last name', type: 'text', reference: 'lastname'},
{ name: 'description', type: 'textarea', reference: 'description'},
{ name: 'option', type: 'checkbox', reference: 'option'},
{ name: 'select', type: 'select', reference: 'select', options:['One','Two','Three'], placeholder:'Select something'},
{ name: 'radio', type: 'radio', reference: 'select', options:['One','Two','Three']},
],
outputData: {}
}
}
})