JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<div id="app">
<div v-for="(question, index) in questions" class="quiz__question question">
<div class="question__title">
{{index + 1}}. {{question.text}}
</div>
<div class="question__answers">
<div v-for="(ans, i) in question.answers" class="question__answer">
<label>
<input
:type="question.type"
v-model="answers[index].answer"
:value="ans"
:placeholder="['text', 'number'].includes(question.type) ? ans : ''"
>
{{ ans }}
</label>
</div>
<div v-if="question.custom" class="question__answer custom">
<label>
<input
:type="question.type"
v-model="answers[index].answer"
value="custom"
>
свой вариант
</label>
<input
v-if="isCustomAnswer(index)"
v-model="answers[index].customAnswer"
>
</div>
</div>
</div>
<button @click="reset">reset</button>
<pre>{{ JSON.stringify(results, null, 2) }}</pre>
</div>
CSS
.quiz__question {
margin: 5px;
padding: 5px;
border: 1px solid silver;
}
.question__answer {
padding: 2px;
margin: 2px;
height: 20px;
border: 1px solid silver;
display: inline-flex;
align-items: center;
}
.custom {
background: #ddd;
}
JavaScript
new Vue({
el: '#app',
data: {
questions: [
{ text: 'Жить хочешь?', answers: [ 'да', 'нет', 'не знаю' ], type: 'radio' },
{ text: '43-й президент США?', answers: [ 'Клинтон', 'Буш', 'Обама' ], type: 'radio', custom: true },
{ text: 'Какими языками владеешь?', answers: [ 'C++', 'Java', 'Rust', 'Go' ], type: 'checkbox' },
{ text: 'Обедать будем?', answers: [ 'водка', 'стейк', 'борщ' ], type: 'checkbox', custom: true },
{ text: 'Кстати, а звать тебя как?', answers: [ 'сообщить Ф.И.О.' ], type: 'text' },
{ text: 'А лет тебе сколько, сынок?', answers: [ 'срочно назвать возраст' ], type: 'number' },
],
answers: [],
},
methods: {
isCustomAnswer(index) {
return (
this.questions[index].custom &&
[].concat(this.answers[index].answer).includes('custom')
);
},
reset() {
this.answers = this.questions.map(n => ({
answer: n.type === 'checkbox' ? [] : '',
customAnswer: null,
}));
},
},
computed: {
results() {
return this.answers.map((n, i) => [].concat(n.answer).map(m =>
m === 'custom' && this.questions[i].custom
? n.customAnswer
: m
)).map((n, i) => this.questions[i].type === 'checkbox' ? n : n[0]);
},
},
created() {
this.reset();
},
});