So i have a component to render while using v-for loop to loop question from an array to be answer, at first the component successfully render with no issue, but i notice one things, its only render the title but never updated the component lifecycle when i clicked next button to render the next array, here is my code:
<template>
<v-form v-if="dataShow.length > 0" ref="form">
<v-row v-if="answerError">
<v-col md="8" offset-md="2" sm="10" offset-sm="1" class="pb-0">
<v-alert
dark
class="mb-0"
dismissible
color="red"
elevation="2"
icon="mdi-alert-circle"
>
{{ $t('ANSWER_ERROR') }}
</v-alert>
</v-col>
</v-row>
<v-row v-for="(question, index) in dataShow" :key="index">
<v-col md="8" offset-md="2" sm="10" offset-sm="1">
<v-card>
<v-card-text class="pb-0 mb-0 mt-0">
<v-row>
<v-col cols="12" sm="8" class="pb-0 mb-0 mt-0">
<label class="label-question pt-0 pb-0 mb-0">{{
question.question
}}</label>
</v-col>
<v-col cols="5" class="pb-0 mb-0 pt-0 mt-0">
<p class="label-description pt-0 mb-0">
{{ question.description }}
</p>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
{{ question.required ? '*' : '' }}
{{ question.numeric ? '#' : '' }}
<AnswerTypeText
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Text'"
:question="question"
/>
<AnswerTypeEmail
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Email'"
:question="question"
/>
<AnswerTypeDropdown
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Dropdown'"
:question="question"
/>
<AnswerTypeCheckbox
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Checkbox'"
:question="question"
/>
<AnswerTypeRadio
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Radio'"
:question="question"
/>
<AnswerTypeDatepicker
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Date'"
:question="question"
/>
<AnswerTypeTimepicker
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Time'"
:question="question"
/>
<AnswerTypeTabletype
class="mb-4 pt-0 mt-0 pb-0"
v-if="question.type == 'Multiple'"
:question="question"
/>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row>
<!-- <v-col cols="12" md="12" sm="12" class="d-flex"> -->
<!-- <v-col cols="6" md="6" sm="6">
<v-btn
:disabled="isDisabledB"
ref="back"
medium
elevation=""
color="primary"
@click="onBack"
>Back</v-btn
>
</v-col> -->
<v-col
md="8"
offset-md="2"
sm="10"
offset-sm="1"
class="d-flex mb-3"
v-if="!hideNext"
>
<v-btn
:disabled="isDisabledN"
ref="next"
medium
elevation=""
color="secondary"
@click="onNext"
>Next</v-btn
>
</v-col>
<v-col
v-if="showSubmit"
md="8"
offset-md="2"
sm="10"
offset-sm="1"
class="d-flex mb-3"
>
<v-btn dark color="primary" @click="onSubmit">Submit</v-btn>
</v-col>
<!-- </v-col> -->
</v-row>
</v-form>
</template>
<script>
import { mapState } from 'vuex'
export default {
middleware: ['authenticated'],
props: ['formId'],
data() {
return {
isDisabledN: false,
isDisabledB: false,
showCounted: 10,
currentPage: 1,
options: [],
hideNext: false,
showSubmit: false,
answerError: false,
dataShow: '',
}
},
methods: {
defaultData() {
this.dataShow = this.questions.slice(0, this.showCounted)
},
checkPage() {
if (this.showCounted * this.currentPage >= this.questions.length) {
this.hideNext = true
this.showSubmit = true
this.isDisabledN = true
this.isDisabledB = false
document.body.scrollTop = 0 // For Safari
document.documentElement.scrollTop = 0 // For Chrome, Firefox, IE and Opera
} else if (this.currentPage <= 1) {
this.isDisabledN = false
this.showSubmit = false
this.isDisabledB = true
document.body.scrollTop = 0 // For Safari
document.documentElement.scrollTop = 0 // For Chrome, Firefox, IE and Opera
} else {
this.showSubmit = false
this.isDisabledN = false
this.isDisabledB = false
document.body.scrollTop = 0 // For Safari
document.documentElement.scrollTop = 0 // For Chrome, Firefox, IE and Opera
}
},
onNext() {
if (this.$refs.form.validate()) {
this.dataShow = this.questions.slice(
this.showCounted * this.currentPage,
this.showCounted * this.currentPage + this.showCounted
)
setTimeout(() => {
this.$refs.form.resetValidation()
}, 5000)
setTimeout(() => {
this.$refs.form.reset()
}, 500)
this.currentPage++
this.checkPage()
console.log('data', this.dataShow)
} else {
this.answerError = true
setTimeout(() => {
this.answerError = false
}, 3000)
this.checkPage()
setTimeout(() => {
this.$refs.form.resetValidation()
}, 5000)
}
},
async onSubmit() {
try {
if (this.$refs.form.validate()) {
await this.$store.dispatch('answers/store', this.formId)
//redirect to completed
this.$router.push('/answers/completed')
} else {
this.answerError = true
setTimeout(() => {
this.answerError = false
}, 3000)
document.body.scrollTop = 0 // For Safari
document.documentElement.scrollTop = 0 // For Chrome, Firefox, IE and Opera
}
} catch (err) {
console.log(err)
this.$store.commit('alerts/show', {
type: 'error',
message: err.response
? this.$t(err.response.data.message)
: this.$t('SERVER_ERROR'),
})
}
},
},
computed: {
...mapState('questions', ['questions']),
},
mounted() {
setTimeout(() => {
this.defaultData()
this.checkPage()
}, 500)
},
}
</script>
and here is an example on how i use the created lifecylce to keep update the component when it renders… but it never update it… only the title of the component and not the answerrules of the component….
<template>
<v-text-field
name="answer"
v-model="answer"
:rules="answerRule"
placeholder="[email protected]"
@keyup="typing"
/>
</template>
<script>
export default {
props: ['question'],
data() {
return {
timer: null,
answer: null,
answerRule: [],
}
},
methods: {
async typing() {
try {
clearTimeout(this.timer)
this.timer = setTimeout(async () => {
let payload = {
questionId: this.question.id,
value: this.answer,
questionName: this.question.question,
}
//update question
await this.$store.commit('answers/update', payload)
}, 1000)
} catch (err) {
this.$store.commit('alerts/show', {
type: 'error',
message: err.response
? this.$t(err.response.data.message)
: this.$t('SERVER_ERROR'),
})
}
},
},
created() {
if (this.question.required) {
this.answerRule.push((v) => !!v || this.$t('QUESTION_REQUIRED'))
this.answerRule.push(
(v) =>
/^(([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/.test(
v
) || this.$t('EMAIL_INVALID')
)
}
this.answerRule.push(
(v) =>
/^(([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/.test(
v
) || this.$t('EMAIL_INVALID')
)
},
}
</script>
is there a way to override it? or there is and best practice on how to keep the components updated…