3

I'm using Vue.js to create a survey with multiple pages. Everything works, except I need to make browser back/forward buttons to do the same as Previous/Next buttons on the page.

I have googled multiple times, but I couldn't come up with any solution for the moment...

I know that I could use vue-router, but I don't know how to adapt it.

How can I achieve this?

HTML

<!DOCTYPE html> ***head*** <body> <div id="app"> <h1>{{ survey.title }}</h1> <div id="survey" v-for="(question, index) in survey.questions"> <div v-show="index === questionIndex"> <h3>{{ question.text }}</h3> <div v-if="questionIndex === 2"> <input type="text" v-model="userResponses[2]" placeholder="Please enter your location:"> </div> <div v-else-if="questionIndex === 4"> <select v-model="question4" multiple> <option v-for="response in question.responses"> {{ response.text }} </option></select> </div> <div v-else-if="questionIndex === 5"> <select v-model="question5" multiple> <option v-for="response in question.responses"> {{ response.text }} </option></select> </div> <div v-else> <ol> <li v-for="response in question.responses"> <label> <input type="radio" v-bind:value="response" v-bind:name="index" v-model="userResponses[index]"> {{ response.text }} </label> </li> </ol> </div> <div id="container"> <button id="left" v-if="questionIndex > 0" v-on:click="prev">Previous</button> <button id="right" v-on:click="next">Next</button> </div> </div> </div> <div v-show="questionIndex === survey.questions.length"> <h2>Thank you for taking our survey!</h2> <p>{{ userResponses }}</p> <p>{{ question4 }}</p> <p>{{ question5 }}</p> </div> </div> <footer>&copy; 2018 George Salukvadze for ***</footer> </body> </html> 

Vue.js

window.onload = survey; function survey(){ var survey = { title: 'Welcome to online survey for Liquid!', questions: [ { text: "What is your age group?", responses: [ {text: '15-24'}, {text: '25-34'}, {text: '35-44'}, ] }, { text: "What is your gender?", responses: [ {text: 'Male'}, {text: 'Female'}, {text: 'Do not identify'}, ] }, { text: "Where do you live?", responses: [ {text: 'Please enter your location'}, ] }, { text: "Do you like to shop?", responses: [ {text: 'Yes'}, {text: 'No'}, ] }, { text: "Select your favorite things to buy:", responses: [ {text: 'Clothing'}, {text: 'Lingerie'}, {text: 'Shoes'}, {text: 'Devices'}, {text: 'Cars'}, ] }, { text: "Please select your favorite brands:", responses: [ {text: 'Sandro'}, {text: 'Maje'}, {text: 'Sony'}, {text: 'Ferrari'}, {text: 'BMW'}, {text: 'Asus'}, ] } ] }; new Vue({ el: '#app', data: { survey: survey, questionIndex: 0, userResponses: Array(survey.questions.length), question4: Array(5), question5: Array(9), }, methods: { next: function() { this.questionIndex++; }, prev: function() { this.questionIndex--; } } }); } 
2
  • This isn't your answer, but I think this could be a problem: defining survey inside a function won't let it have global scope right? I think you need to put the new Vue({...}) code in the onload handler. Commented Mar 11, 2018 at 13:41
  • @RobertMoore, thanks for your comment. The page itself works quite well, only thing is that browser Back button doesn't go back to previous question (for example), but goes back to page previously opened by browser. So you think that your idea might solve this? I'll give it a try and get back to you Commented Mar 11, 2018 at 17:20

1 Answer 1

4

You could use the vue-router as you implied. The simplest solution for your example, though, is to just use the browser's history API. Steps:

  • When moving to previous/next questions, use history.pushState to add a state to the browser's history:

     methods: { next: function() { this.questionIndex++; this.updateHistory(); // added this line }, prev: function() { this.questionIndex--; this.updateHistory(); // added this line }, updateHistory: function() { // added this method history.pushState({questionIndex: this.questionIndex}, "Question " + this.questionIndex); } } 
  • And now all you have to do is listen to those history state changes. A good spot to hook a listener to this event is the mounted:

     mounted: function() { var vm = this; window.addEventListener('popstate', function(event) { vm.questionIndex = (event.state || {questionIndex: 0}).questionIndex; }); }, 

And that's it.

Click here for the a demo page at JSBin (check the history button).

You'll find the source for that demo here.

Sign up to request clarification or add additional context in comments.

2 Comments

as long as we are here, I would like also to implement a cookie, so that the state of survey is saved on browser close. could you help me out?
You should open a new question, so others may help you as well. You may need a plugin to handle cookies.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.