Reputation: 263
I have an image with 3 areas. When I click on each area, I want a series of questions to appear. I've done this, but I want to change it a bit. Since I don't want to redirect it to a page, I am giving # as href link and I'm getting the id of the area based by event.currentTarget.id Then I have three v-ifs with a condition for each component.
This is the jfiddle: https://jsfiddle.net/rau4apyg/
<div id="app">
<img id="Image-Maps-Com-image-maps-2017-03-16-100553" src="http://www.image-maps.com/m/private/0/fdfutap3klci37abfmuasc2mk7_screenshot.png" border="0" width="588" height="414" orgWidth="588" orgHeight="414" usemap="#image-maps-2017-03-16-100553" alt="" />
<map name="image-maps-2017-03-16-100553" id="ImageMapsCom-image-maps-2017-03-16-100553">
<area shape="rect" coords="586,412,588,414" alt="Image Map" style="outline:none;" title="Image Map" href="http://www.image-maps.com/index.php?aff=mapped_users_0" />
<area id="component1" alt="" title="comp1" href="#" shape="poly" coords="420,228,296,34,180,226,178,228" style="outline:none;" target="_self" v-on:click="compId($event)" />
<area id="component2" alt="" title="comp2" href="#" shape="poly" coords="92,368,176,234,292,234,294,368,298,236,290,368" style="outline:none;" target="_self" v-on:click="compId($event)" />
<area id="component3" alt="" title="comp3" href="#" shape="poly" coords="506,366,296,366,296,232,422,232" style="outline:none;" target="_self" v-on:click="compId($event)" />
</map>
<h1> Title here </h1>
<div v-if="compid === 'component1'">
component1 is clicked, questions are shown
</div>
<!-- show questions in for loop -->
<div v-if="compid === 'component2'">
2 is clicked
</div>
<div v-if="compid === 'component3'">
3 is clicked
</div>
<div v-show="questionIndex === quiz.questions.length -1">
<button v-on:click="addAnswers">
submit
</button>
<h2>
Quiz finished, plase continue with Component 2 questions.
</h2>
<button v-on:click="goToNextComponent">
Next
</button>
</div>
new Vue({
el: '#app',
data: {
quiz: {
questions: [],
answers: []
},
// Store current question index
questionIndex: 0,
total:0,
show: true,
compid: '',
flag: false
},
mounted: {
//functions here
},
computed: {
//functions here
},
// The view will trigger these methods on click
methods: {
//some functions
//return id of clicked component
compId: function(event){
this.compid = event.currentTarget.id;
console.log(event.currentTarget.id); // returns the name of the id clicked.
} ,
addAnswers: function(){
//store answers in Firebase
//vm.$forceUpdate();
flag = true; //change the flag
console.log(flag);
},
goToNextComponent: function(){
}
}
});
I want to complete the questions in order, that means: First do questions of Component1, click submit to save the answers, then show questions of Component2, answer them and then move to Component3.
If a user is done with Component1, I want him to not be able to answer these questions again, disable it in some way, and go to component 2. When he completes the next component, I want to disable that too and go to the last one.
I don't know how to make it work this way. I had two thoughts: 1) When I click the Submit button, I change a flag to true. So I know component 1 is clicked and I add it to the v-if clause. I tried adding it by using an && operator but it didn't work. 2) Have a next button after submit (I am not sure if it sounds ok) and when that is clicked, show the next questions that are included in component 2.
P.S.My database is on Firebase and I have all the questions in an array. e.g. First 10 questions are of component1, next 8 of component 2, etc. Maybe would it be better to add a field to seperate them? Right now it's like this:
{
"questions" : [ {
"q_options" : [ "Yes", "No", "Don't know" ],
"q_text" : "Do you agree with blah blah?"
}}
Maybe I could add a component_option: 1 Any ways you would suggest to solve these problems?
Upvotes: 2
Views: 2691
Reputation: 82459
I've modified your approach a little bit. Essentially you were on the right track; you just need to keep track of which questions are completed. Then, when someone clicks on a particular image map, check to see if that has already been completed and, if so, prevent navigating to it.
const quiz = new Vue({
el: '#app',
data: {
quiz: {
questions: [
{
"q_options" : [ "Yes", "No", "Don't know" ],
"q_text" : "Do you agree with blah blah?",
coords:"420,228,296,34,180,226,178,228",
shape:"poly",
completed: false,
answer: null
},
{
"q_options" : [ "Yes", "No", "Don't know" ],
"q_text" : "Question Number 2?",
coords:"92,368,176,234,292,234,294,368,298,236,290,368",
shape: "poly",
completed: false,
answer: null
},
{
"q_options" : [ "Yes", "No", "Don't know" ],
"q_text" : "Question Number 3?",
coords:"506,366,296,366,296,232,422,232",
shape:"poly",
completed: false,
answer: null
}],
answers: []
},
currentQuestion: null,
quizCompleted: false
},
methods: {
selectQuestion(question){
if (!question.completed)
this.currentQuestion = question;
else
alert("This question has already been completed!")
},
completeQuestion(){
this.currentQuestion.completed = true;
let currentIndex = this.quiz.questions.indexOf(this.currentQuestion);
if ( currentIndex === this.quiz.questions.length - 1){
this.quizCompleted = true;
this.currentQuestion = null;
this.quiz.answers = this.quiz.questions.map(q => q.answer)
} else {
this.currentQuestion = this.quiz.questions[++currentIndex];
}
}
},
mounted(){
this.currentQuestion = this.quiz.questions[0]
}
});
And the template:
<div id="app">
<img id="Image-Maps-Com-image-maps-2017-03-16-100553" src="http://www.image-maps.com/m/private/0/fdfutap3klci37abfmuasc2mk7_screenshot.png" border="0" width="588" height="414" orgWidth="588" orgHeight="414" usemap="#image-maps-2017-03-16-100553" alt="" />
<map name="image-maps-2017-03-16-100553" id="ImageMapsCom-image-maps-2017-03-16-100553">
<area v-for="question in quiz.questions"
:shape="question.shape"
:coords="question.coords"
@click="selectQuestion(question)"/>
</map>
<div v-if="currentQuestion">
<h1> {{currentQuestion.q_text}} </h1>
<template v-for="(option, index) in currentQuestion.q_options">
<input type="radio" :value="option" v-model="currentQuestion.answer">
<label>{{option}}</label>
<br />
</template>
<button @click="completeQuestion">Complete</button>
</div>
<div v-if="quizCompleted">
<h1>You're Done!</h1>
{{quiz.answers}}
</div>
</div>
Here is a working example.
Some key points.
This is not polished, but it accomplishes your main goal; using the map for navigation, and preventing navigating to completed questions.
Upvotes: 2