1
votes

I want to get the value of the checkbox that is checked and the input that was given by the user for that specific checkbox. I can get the value of checked checkbox the problem is getting the value of input text.

Issue One :It works but is there a better way of doing it ?????? Issue Two : There are other checkbox in the form when the checkcbox is clicked a second time instead of disbling all other checkbox get clicked , when clicked third time it gets disabled

Note : Noob here Please advise

<template>
  <div >
    <form>
      
      <input type="checkbox" v-bind:value="question" @change="getAnswer($event)" v-model="correctAnswer" />
      <label for="question">Question</label>
    </form>

    <div id="preview">
      <p>Correct Answer :{{ model.correctAnswer }}</p>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      model: {
        question: "",
        correctAnswer: "",
      },
    };
  },
  methods: {
    getAnswer: function() {
   
      if(this.model.correctAnswer==""){
         this.model.correctAnswer=this.model.question
    
      }
      else{
        this.model.correctAnswer =""
      }
     
    },
  },
};
</script>

2

2 Answers

0
votes

It's not clear to me what you want, but I try to guess: you would like to build a poll template builder - am I right?

If yes then here's a snippet for you to use:

// component for one option
const QuestionOption = {
  props: ['idx'],
  template: `
    <div>
      <input type="checkbox"
        v-model="isCorrect"
        @change="setCorrect(isCorrect)"
      />
      <label>Option {{ idx + 1 }}:</label>
      <input type="text"
        v-model="optionText"
        @input="setOptionText(optionText)"
      />
    </div>
  `,
  data() {
    return {
      isCorrect: false,
      optionText: ''
    }
  },
  methods: {
    setCorrect(e) {
      this.$emit('set-correct', {
        idx: this.idx,
        isCorrect: e
      })
    },
    setOptionText(text) {
      this.$emit('set-option-text', {
        idx: this.idx,
        optionText: text
      })
    }
  }
}

// component for the whole question
const QuestionItem = {
  components: {
    QuestionOption
  },
  template: `
    <div>
      Question: 
      <input type="text"
        v-model="question"
      />
      <question-option
        v-for="(item, idx) in correctAnswers"
        :key="idx"
        :idx="idx"
        @set-correct="setCorrect"
        @set-option-text="setOptionTextAtIdx"
      />
    </div>
  `,
  data() {
    return {
      question: '',
      correctAnswers: [false, false, false, false],
      optionTexts: []
    }
  },
  methods: {
    setCorrect(e) {
      this.correctAnswers[e.idx] = e.isCorrect
      this.setQuestionData(this.question, this.correctAnswers, this.optionTexts)
    },
    setOptionTextAtIdx({
      idx,
      optionText
    }) {
      this.optionTexts[idx] = optionText
      this.setQuestionData(this.question, this.correctAnswers, this.optionTexts)
    },
    setQuestionData(question, correctAnswers, optionTexts) {
      this.$emit('set-question-data', {
        question,
        correctAnswers,
        optionTexts
      })
    }
  },
  watch: {
    question: function(val) {
      this.setQuestionData(val, this.correctAnswers, this.optionTexts)
    }
  }
}

// component for previewing the question & correct answers
const Preview = {
  props: ['question'],
  computed: {
    correctAnswerList() {
      return this.question.correctAnswers.map((e, idx) => {
        return {
          isCorrect: e,
          text: `Option ${ idx + 1 }`
        }
      }).filter(({
        isCorrect
      }) => isCorrect).map(({
        text
      }) => text).join(', ')
    }
  },
  template: `
    <div>
      Question: {{ question.question }}<br />
      <div
        v-for="(option, idx) in question.correctAnswers"
        :key="idx + '-' + Date.now()"
      >
        Option {{ idx + 1 }}: {{ question.optionTexts[idx] }}
      </div>
      <div>
        Correct Answers: {{ correctAnswerList }}
      </div>
    </div>
  `
}

// Vue instance - aggregating the data for the question
new Vue({
  el: '#app',
  components: {
    QuestionItem,
    Preview
  },
  data() {
    return {
      question: {
        question: '',
        correctAnswers: [],
        optionTexts: []
      }
    }
  },
  methods: {
    setPreview(questionData) {
      this.question = questionData
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <question-item @set-question-data="setPreview"></question-item>
  <preview :question="question"></preview>
</div>

When you think about the Vue app structure you should always think about how your data structure builds up:

  • you have options, that are either true or false AND have a variable text
  • the question should always "know" which of its options are "correct answers" and what is the text content of the options AND also has the question (variable text)
  • the main Vue instance should always "know" all the data the question "knows", because there's another branch of component(s) that should be updated (the preview)
  • the preview is just a presentational component - it gets everything from its parent (in this case the Vue instance)

If you have this dataflow in your head, then you can design the components:

  • one for the option (used many times) - it should hold data and should inform its parent about the changes in its data (hence the emitted events: this.$emit())
  • one for the whole question - it should contain the options & the question itself and should also inform its parent if something changes in its content (emit & re-emit events)
  • one for the preview that displays the question setup
  • one Vue instance that holds the things together

And voilá! This small app is designed - now you just have to code it (snippet).

I understand that for a beginner this may seem a bit too complex for a task such as you described (or I understood), but this is more about the logic how to build something that is easily extendable. For example: if you just initialize the QuestionItem with one more false in its correctAnswers data, then you have one more Option to use.

0
votes

The answer by @muka.gergely is the right way to do the entire app .

If only the checkbox and input binding needs to be done . It can be done this way

<input type="checkbox"  v-bind:data-id="model.question" @change="getAnswer($event)"  />
      <label for="question">Question</label>
      <input type="text" required v-model.lazy="model.question" />


methods:{
    getAnswer: function(e){
     let xray = e.currentTarget.getAttribute('data-id')
console.log(xray)
      if(this.model.correctAnswer==""){
         this.model.correctAnswer=xray
    
      }
      else{
        this.model.correctAnswer =""
      }
    }
  }