I've got this quiz app.
I've got a question and 4 answer each, there are 10 questions and each time they are shown randomly.
I've got a button that when it's triggered it should delete 2 of the 4 displayed answers, always keeping the correct answer in obviously.
So I need to delete two elements from an object cause my questions array is formed by ten of these objects:
{
domanda: "Quando è iniziata la prima guerra mondiale?",
risposte: { a: "1993", b: "1910", c: "1915", d: "1879" },
rispostaCorretta: "c",
},
So considering this question, when I click on that button it should delete 2 answers (a, b or d) and let the c answer always in cause it's the correct one.
Here's the function that should do the job:
getHalf(obj) {
console.log(obj)
for(var k in obj.risposte) {
console.log(k)
if(k != obj.rispostaCorretta) {
this.$delete(k, obj.risposte)
}
}
}
At the moment it gives me these errors:
Cannot delete reactive property on undefined, null, or primitive value: a
Cannot delete reactive property on undefined, null, or primitive value: b
Cannot delete reactive property on undefined, null, or primitive value: c
This is the current object:
{
domanda: "Chi era il frontman dei Queen?",
risposte: {
a: "Zlatan",
b: "Er Freddo",
c: "Otello Lupacchini",
d: "Freddy Mercury",
},
rispostaCorretta: "d",
},
The d is the correct answer so at least that is working, now it should be 2 of the others and not 3.
This is the button, i'm passing in the current question each time
<button @click="getHalf(domande[domandaCorrente])">50/50</button>
I tried with Vue.delete(...) or this.$delete('a', obj) but it didn't work, it give me back this error most of the time: Cannot delete reactive property on undefined, null, or primitive value: a
How can I solve this?? Help me if you can please.
I leave here the whole Vue template
<template>
<div class="question">
<div class="q" v-if="domandaCorrente < domande.length && !finish">
<h2 class="border">{{ domande[domandaCorrente].domanda }}</h2>
<!-- <Answer @selectAnswer="setAnswer" :domande="domande" /> -->
<div class="answer">
<label
class="answer-label border hide"
:for="index"
v-for="(risposta, index) in domande[domandaCorrente].risposte"
:key="index"
:class="{
hover: domandaScelta == '',
'bg-red': domandaScelta == index,
'bg-green':
index == domande[domandaCorrente].rispostaCorretta &&
domandaScelta != '',
}"
>
<input
type="radio"
:checked="index == selected"
:name="index"
:id="index"
class="hidden"
:value="index"
@change="select($event)"
/>
<h4 class="index">{{ index }}</h4>
<h4 class="actual-answer">{{ risposta }}</h4>
</label>
<button @click="getHalf(domande[domandaCorrente])">50/50</button>
<div
v-show="
domandaScelta != '' &&
domandaCorrente < domande.length - 1 &&
!finish
"
class="button"
>
<button v-show="!endGame" @click="nextQuestion()">
Vai alla domanda da {{ nextPrice | toCurrency }} €
</button>
<h4 class="wrong" v-show="endGame">Hai Sbagliato!</h4>
</div>
<div
v-show="
domandaScelta != '' &&
domandaCorrente == domande.length - 1 &&
!finish
"
class="button"
>
<button @click="showResult()">Finish</button>
</div>
</div>
</div>
<div v-else-if="finish || domandaCorrente == domande.length">
<div class="end">
<!-- <h2>
Correct Answers: <span class="t-green">{{ correct }}</span>
</h2> -->
<h2 v-show="domandaCorrente != domande.length">Ti sei fermato alla domanda {{ domandaCorrente 1 }}</h2>
<h2 v-show="domandaCorrente == domande.length" >Complimenti! Hai completato la scalata!</h2>
<h5 style="margin: 30px 0">Torni a casa con</h5>
<h2 style="color: gold; font-size: 3rem">
{{ finalPrice | toCurrency }} €
</h2>
<button class="reload" @click="reloadQuiz()">
Inizia di nuovo la scalata!
</button>
</div>
</div>
</div>
</template>
<script>
import Vue from "vue";
export default {
name: "Question",
data() {
return {
// random: 0,
half: false,
domandaCorrente: 0,
correct: 0,
nextPrice: 0,
wrong: 0,
endGame: false,
domandaScelta: "",
selected: false,
finish: false,
gift: [1000, 2000, 3000, 5000, 10000, 15000, 25000, 40000, 50000, 100000],
finalPrice: 0,
domande: [
{
domanda: "Quante champions ha vinto il Milan?",
risposte: { a: "2", b: "5", c: "7", d: "10" },
rispostaCorretta: "c",
},
{
domanda: "La capitale della Romania?",
risposte: { a: "Bucarest", b: "Milano", c: "Berlino", d: "Oslo" },
rispostaCorretta: "a",
},
{
domanda: "Chi ha scoperto l'America?",
risposte: {
a: "Cristoforo Colombo",
b: "Carlo Pellegatti",
c: "216",
d: "Amerigo Vespucci",
},
rispostaCorretta: "a",
},
{
domanda: "Quando è iniziata la prima guerra mondiale?",
risposte: { a: "1993", b: "1910", c: "1915", d: "1879" },
rispostaCorretta: "c",
},
{
domanda: "Chi era il frontman dei Queen?",
risposte: {
a: "Zlatan",
b: "Er Freddo",
c: "Otello Lupacchini",
d: "Freddy Mercury",
},
rispostaCorretta: "d",
},
{
domanda: "A quale temperatura bolle l'acqua?",
risposte: { a: "10°", b: "5°", c: "70°", d: "100°" },
rispostaCorretta: "d",
},
{
domanda: "Chi ha vinto gli europei nel 2021",
risposte: { a: "Spagna", b: "Germania", c: "Italia", d: "Danimarca" },
rispostaCorretta: "c",
},
{
domanda: "Quale di queste è una funzione?",
risposte: {
a: "let item = 23",
b: "function getItem() ...",
c: "return",
d: "string.join()",
},
rispostaCorretta: "b",
},
{
domanda: "Come si passano dati ad un componente figlio in Vue?",
risposte: { a: "Props", b: "Emit", c: "Componenti", d: "Altro" },
rispostaCorretta: "a",
},
{
domanda: "Quante champions ha vinto la Juve?",
risposte: { a: "2", b: "5", c: "7", d: "10" },
rispostaCorretta: "a",
},
],
};
},
methods: {
select(e) {
this.selected = e.target.value;
this.domandaScelta = e.target.value;
// console.log(this.domandaScelta);
// console.log(this.domandaCorrente);
if (
this.domandaScelta ==
this.domande[this.domandaCorrente].rispostaCorretta
) {
this.correct ;
this.finalPrice = this.gift[this.domandaCorrente];
this.nextPrice = this.gift[this.domandaCorrente 1];
this.finish = false;
} else {
// this.reload();
this.endGame = true;
setTimeout(() => {
this.finish = true;
}, 1500);
// this.wrong
}
},
shuffleVueArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i 1));
const temp = array[i];
Vue.set(array, i, array[j]);
Vue.set(array, j, temp);
}
},
nextQuestion() {
this.domandaScelta = "";
this.selected = false;
this.domandaCorrente ;
},
showResult() {
this.domandaCorrente ;
},
reloadQuiz() {
location.reload();
},
toCurrency() {
Vue.filter("toCurrency", function (value) {
if (typeof value !== "number") {
return value;
}
var formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 0,
});
return formatter.format(value);
});
},
getHalf(obj) {
console.log(obj)
for(var k in obj.risposte) {
console.log(k)
if(k != obj.rispostaCorretta) {
this.$delete(k, obj.risposte)
}
}
}
},
created() {
this.shuffleVueArray(this.domande);
this.toCurrency();
},
};
</script>
CodePudding user response:
Your question is a little complex, but I think I got your main question, you want to remove 2 answers from 4 answers.
If the question object comes from props, you should not mutate it directly, you have to create a clone from it, then can mutate and use the cloned question.
In this example, I watch the prop value, whenever there is a new value I put it inside a tempQuestion, and then I can mutate the tempQuestion by a method.
// inside vue component
{
props: {
question: Object,
},
data() {
return {
tempQuestion: null,
}
},
watch: {
question: {
deep: true,
immediate: true,
handler(newValue) {
this.tempQuestion = newValue;
},
}
},
methods: {
removeAnswers() {
delete this.tempQuestion.risposte.a
}
}
}
CodePudding user response:
Try this way to remove 2 answers :
getHalf(obj) {
let nr = 0
const removeProperty = (propKey, { [propKey]: propValue, ...rest }) => rest;
for(var k in obj.risposte) {
if (nr < 2) {
if(k != obj.rispostaCorretta) {
obj.risposte = removeProperty(k, obj.risposte);
nr
}
} else return
}
},
new Vue({
el: '#demo',
name: "Question",
data() {
return {
// random: 0,
half: false,
domandaCorrente: 0,
correct: 0,
nextPrice: 0,
wrong: 0,
endGame: false,
domandaScelta: "",
selected: false,
finish: false,
gift: [1000, 2000, 3000, 5000, 10000, 15000, 25000, 40000, 50000, 100000],
finalPrice: 0,
domande: [
{
domanda: "Quante champions ha vinto il Milan?",
risposte: { a: "2", b: "5", c: "7", d: "10" },
rispostaCorretta: "c",
},
{
domanda: "La capitale della Romania?",
risposte: { a: "Bucarest", b: "Milano", c: "Berlino", d: "Oslo" },
rispostaCorretta: "a",
},
{
domanda: "Chi ha scoperto l'America?",
risposte: {
a: "Cristoforo Colombo",
b: "Carlo Pellegatti",
c: "216",
d: "Amerigo Vespucci",
},
rispostaCorretta: "a",
},
{
domanda: "Quando è iniziata la prima guerra mondiale?",
risposte: { a: "1993", b: "1910", c: "1915", d: "1879" },
rispostaCorretta: "c",
},
{
domanda: "Chi era il frontman dei Queen?",
risposte: {
a: "Zlatan",
b: "Er Freddo",
c: "Otello Lupacchini",
d: "Freddy Mercury",
},
rispostaCorretta: "d",
},
{
domanda: "A quale temperatura bolle l'acqua?",
risposte: { a: "10°", b: "5°", c: "70°", d: "100°" },
rispostaCorretta: "d",
},
{
domanda: "Chi ha vinto gli europei nel 2021",
risposte: { a: "Spagna", b: "Germania", c: "Italia", d: "Danimarca" },
rispostaCorretta: "c",
},
{
domanda: "Quale di queste è una funzione?",
risposte: {
a: "let item = 23",
b: "function getItem() ...",
c: "return",
d: "string.join()",
},
rispostaCorretta: "b",
},
{
domanda: "Come si passano dati ad un componente figlio in Vue?",
risposte: { a: "Props", b: "Emit", c: "Componenti", d: "Altro" },
rispostaCorretta: "a",
},
{
domanda: "Quante champions ha vinto la Juve?",
risposte: { a: "2", b: "5", c: "7", d: "10" },
rispostaCorretta: "a",
},
],
};
},
methods: {
select(e) {
this.selected = e.target.value;
this.domandaScelta = e.target.value;
// console.log(this.domandaScelta);
// console.log(this.domandaCorrente);
if (
this.domandaScelta ==
this.domande[this.domandaCorrente].rispostaCorretta
) {
this.correct ;
this.finalPrice = this.gift[this.domandaCorrente];
this.nextPrice = this.gift[this.domandaCorrente 1];
this.finish = false;
} else {
// this.reload();
this.endGame = true;
setTimeout(() => {
this.finish = true;
}, 1500);
// this.wrong
}
},
shuffleVueArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i 1));
const temp = array[i];
Vue.set(array, i, array[j]);
Vue.set(array, j, temp);
}
},
nextQuestion() {
this.domandaScelta = "";
this.selected = false;
this.domandaCorrente ;
},
showResult() {
this.domandaCorrente ;
},
reloadQuiz() {
location.reload();
},
toCurrency() {
Vue.filter("toCurrency", function (value) {
if (typeof value !== "number") {
return value;
}
var formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 0,
});
return formatter.format(value);
});
},
getHalf(obj) {
let nr = 0
const removeProperty = (propKey, { [propKey]: propValue, ...rest }) => rest;
for(var k in obj.risposte) {
if (nr < 2) {
if(k != obj.rispostaCorretta) {
obj.risposte = removeProperty(k, obj.risposte);
nr
}
} else return
}
},
},
created() {
this.shuffleVueArray(this.domande);
this.toCurrency();
},
});
Vue.config.productionTip = false
Vue.config.devtools = false
.answer {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div class="question">
<div class="q" v-if="domandaCorrente < domande.length && !finish">
<h2 class="border">{{ domande[domandaCorrente].domanda }}</h2>
<!-- <Answer @selectAnswer="setAnswer" :domande="domande" /> -->
<div class="answer">
<label
class="answer-label border hide"
:for="index"
v-for="(risposta, index) in domande[domandaCorrente].risposte"
:key="index"
:class="{
hover: domandaScelta == '',
'bg-red': domandaScelta == index,
'bg-green':
index == domande[domandaCorrente].rispostaCorretta &&
domandaScelta != '',
}"
>
<input
type="radio"
:checked="index == selected"
:name="index"
:id="index"
class="hidden"
:value="index"
@change="select($event)"
/>
<h4 class="index">{{ index }}</h4>
<h4 class="actual-answer">{{ risposta }}</h4>
</label>
<button @click="getHalf(domande[domandaCorrente])">50/50</button>
<div
v-show="
domandaScelta != '' &&
domandaCorrente < domande.length - 1 &&
!finish
"
class="button"
>
<button v-show="!endGame" @click="nextQuestion()">
Vai alla domanda da {{ nextPrice | toCurrency }} €
</button>
<h4 class="wrong" v-show="endGame">Hai Sbagliato!</h4>
</div>
<div
v-show="
domandaScelta != '' &&
domandaCorrente == domande.length - 1 &&
!finish
"
class="button"
>
<button @click="showResult()">Finish</button>
</div>
</div>
</div>
<div v-else-if="finish || domandaCorrente == domande.length">
<div class="end">
<!-- <h2>
Correct Answers: <span class="t-green">{{ correct }}</span>
</h2> -->
<h2 v-show="domandaCorrente != domande.length">Ti sei fermato alla domanda {{ domandaCorrente 1 }}</h2>
<h2 v-show="domandaCorrente == domande.length" >Complimenti! Hai completato la scalata!</h2>
<h5 style="margin: 30px 0">Torni a casa con</h5>
<h2 style="color: gold; font-size: 3rem">
{{ finalPrice | toCurrency }} €
</h2>
<button class="reload" @click="reloadQuiz()">
Inizia di nuovo la scalata!
</button>
</div>
</div>
</div>
</div>