I have a fill in the blank question. Each time an input is correct I want to emit back to the parent so that when all are correct I can display a success message.
I figured I could just use a simple counter to increment by one each time the $emit came to the parent but always on the last try I get an infinite loop. I don't understand what I am doing wrong. I tried to strip out my files as much as possible to show what I believe is relevant and you can get an idea of how it works. Is it something with how the parent loops of the question or something?
Thanks for any help you can give.
Parent Component
Parent component takes a JOSN string like "There are *_* letters in the *_* alphabet" and splits it into spans for the text and inputs for the *_* then reassembles it. The answers would be 26 and English
The parts of trouble in parent is the function questionSuccess()
<template>
<div class="interactive interactive-vue-question interactive-vue-question-iv">
<component
:is="buildQuestion(index)"
v-for="(item, index) in questionParts"
ref="ivWrap"
:key="index"
:question-props="item.includes('*_*') ? matchedOptions[index] : item"
@success="questionSuccess"
/>
</div>
</template>
<script>
export default {
name: 'IvV1',
components: {
ivInput,
ivText,
},
props: ['cData'],
data: function () {
return {
questionParts: [],
matchedOptions: [],
options: this.cData.body.options,
optionsIndex: 0,
answerBtnText: 'Show Answer(s)',
showAnswers: false,
showHints: false,
showModal: false,
counter: 0
}
},
created () {
const { questionText } = this.cData.body
// Split the array at any whitespace character, and groups *_* an returns an array
this.questionParts = questionText.split(/\s*(\*_\*)\s*/)
// Filter out any empty array items so there's no extra unkown values
this.questionParts = this.questionParts.filter(function (e) { return e })
console.log(this.showHints)
},
beforeMount: function () {
// Find all the questionParts
for (let x = 0; x < this.questionParts.length; x++) {
// If input placeholder is found push the corresponding answer from answers into matchedAnswers array
if (this.questionParts[x].includes('*_*')) {
this.matchedOptions.push(this.options[this.optionsIndex])
this.optionsIndex++
} else {
// If not push an empty string
this.matchedOptions.push('')
}
}
},
methods: {
buildQuestion: function (index) {
// Find the question parts that inlude *_* and push an input to array otherwise push the <span> text </span>
if (this.questionParts[index].includes('*_*')) {
return ivInput
} else {
return ivText
}
},
// THIS IS WHERE I AM TRYING TO COUNT EACH TIME IT RUNS
questionSuccess: function () {
this.counter++
console.log(this.counter)
},
}
}
</script>
Input Component
Each input is validated separately so when each input is correct I want to emit that success to parent. Then in parent count the times it has been emitted so I can show a message but I get infinite loop on last correct input
I emit 'success' after isCorrect()
<template>
<div class="iv-input-wrap" :class="[{'is-error': isError, 'is-correct': isCorrect}]">
<input
ref="iv"
v-model="userInput"
type="text"
class="iv-input"
:class="[{'is-correct':isCorrect, 'is-error':isError}]"
:disabled="isCorrect"
>
</div>
</template>
<script>
export default {
name: 'IvInput',
props: [
'cData',
'questionProps',
],
data: function () {
return {
userInput: '',
errorMessage: '',
showPadding: this.questionProps.showPadding,
displayErrorMessage: this.cData.config.displayErrorMessage,
}
},
computed: {
isCorrect: function () {
if (this.isType === true && this.isMatch === true) {
this.$emit('success')
return true
}
},
isError: function () {
// If isType has failed and displayErrorMessages are turned on return
if (this.isType === false && this.displayErrorMessage === true) {
this.$nextTick(function () {
new Popper(this.$refs.iv, this.$refs.errorPopper, {
placement: 'bottom'
})
})
return true
}
},
hideErrorMessage: function () {
// If Display error message has been turned off
if (this.isType === false && this.displayErrorMessage === false) {
return true
}
},
isType: function () {
// If the answer type is a string
let charRegex
if (this.questionProps.type === 'string') {
// Check what the accent allowed is
if (this.questionProps.accent === true) {
// Allow alpha and accented characters
charRegex = /^[A-Za-z\u00C0-\u024F]+$/
this.errorMessage = 'Letters Only'
} else {
// Allow alpha characters only
charRegex = /^[A-Za-z]+$/
this.errorMessage = 'Letters only'
}
// Check if the user has typed anything, if so match input to char-regex
if (this.userInput.length > 0) {
if (this.userInput.match(charRegex)) {
return true
} else {
return false
}
}
} // End if is string
},
isMatch: function () {
// If isType has not passed then we don't need to proceed
let checkCase
if (this.isType === true) {
checkCase = this.userInput.localeCompare(
this.questionProps.answer, { sensitivity: 'case', usage: 'search' })
} // end isType true
} // end isMatch
},
}
</script>