Home > Mobile >  How to delete two elements from an object in Vue.js?
How to delete two elements from an object in Vue.js?

Time:09-24

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 }} &euro;
          </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 }} &euro;
        </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 }} &euro;
          </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 }} &euro;
        </h2>
        <button class="reload" @click="reloadQuiz()">
          Inizia di nuovo la scalata!
        </button>
      </div>
    </div>
  </div>
</div>

  • Related