?
Solved

Create wizard type navigation in MVC

Posted on 2010-09-01
8
Medium Priority
?
957 Views
Last Modified: 2013-11-08
Hi
I’m writing a customer survey app in MVC.
I have a view that is populated by looping through a customer survey and outputs the questions and question choices.  For example

Q1  What would you rate as acceptable?
a.       10 hours  
b.      20 hours
c.      30 hours
Q2 What is the time scale for this issue?
a.      1 hour
b.      2 hours
c.      3 hours

And so on.    In the view all the questions are displayed in one view but I want to break up each question so it is displayed one at a time.

I want to convert the view so it is a in wizard format with a next button so that each question is displayed at one time and when you hit the “next” button the second question is displayed and so on.

For info  this is a snippet of how I loop through the customer survey to populate the view

  <%
            foreach (var qChoice in question.questionChoices)
            { %>
       ................................
0
Comment
Question by:ToString1
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
8 Comments
 
LVL 27

Accepted Solution

by:
nmarun earned 2000 total points
ID: 33575201
There's no need for your to have that foreach loop in the view. Here's how I'd work this up.

Create a view that can display a question and it's choices (a foreach might be required for the choices). Now my controller will give only one question to the view. All I need to know what question was passed to the view (I'll use a hidden field on the view to store the question id).

Once the user hits the 'next' / 'back' button, I can check the formCollection["next"] or formCollection["back"] to have a value in them and decide to display the appropriate question. The 'post' version of your action method might look something like:

[HttpPost]
public ViewResult Survey(Question currentQuestion, FormCollection formCollection)
{
    // save the current question's answer
    Question questionToBeDisplayed;
    if(!string.IsNullOrEmpty(formCollection["next"])
    {
        // display the next question
        questionToBeDisplayed = GetNextQuestion(currentQuestion.Id);
    }
    else // if(!string.IsNullOrEmpty(formCollection["back"])
    {
       // display the previous question
       questionToBeDisplayed = GetPrevQuestion(currentQuestion.Id);
    }

    return View(questionToBeDisplayed);
}
0
 

Author Comment

by:ToString1
ID: 33575249
OK nmarun  an excellent answer.   I will get back to you shortly and try out your solution
0
 

Author Comment

by:ToString1
ID: 33575339

Thanks
Currently I have an controller that accepts a the whole survey answers as a list.......

public ActionResult CompletedSurvey(int? surveyID, List<surveyResponse> Responses)



Could you expand with some more code on how you would go about this please?  


0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ToString1
ID: 33575564
Infact the main thing I need to do is to know how to display each question in turn.   You see I have the questions stored in database table with primary key.

So when I first load the questionnaire how would I know how to display the first question?

So on first load would it be

questionToBeDisplayed = GetNextQuestion(currentQuestion.Id);  //would this be the lowest primary key?


Also are the code

if(!string.IsNullOrEmpty(formCollection["back"])

for the next and back button?

0
 
LVL 27

Assisted Solution

by:nmarun
nmarun earned 2000 total points
ID: 33575868
Here's a working model I have for you.

Arun

// my model class
public class Choice
{
    public int ChoiceId { get; set; }
    public string Text { get; set; }
}

public class Question
{
    public int QuestionId { get; set; }
    public string Text { get; set; }
    public List<Choice> Choices { get; set; }
}

// my controller
private List<Question> questions;
// this code is only for my mock purposes
// you will not be needing this as you'll read it from the database
public HomeController()
{
    questions = new List<Question>();
    questions.Add(new Question
                      {
                          QuestionId = 1,
                          Text = "What is 2x2?",
                          Choices = new List<Choice>
                                        {
                                            new Choice{ ChoiceId = 1, Text = "2" },
                                            new Choice{ ChoiceId = 2, Text = "4" },
                                            new Choice{ ChoiceId = 3, Text = "6" },
                                        }
                      });
    questions.Add(new Question
                      {
                          QuestionId = 2,
                          Text = "What is 26x7",
                          Choices = new List<Choice>
                                        {
                                            new Choice{ ChoiceId = 4, Text = "182" },
                                            new Choice{ ChoiceId = 5, Text = "134" },
                                            new Choice{ ChoiceId = 6, Text = "5" },
                                        }
                      });
    questions.Add(new Question
                      {
                          QuestionId = 3,
                          Text = "What is 25x24?",
                          Choices = new List<Choice>()
                                        {
                                            new Choice{ ChoiceId = 7, Text = "175" },
                                            new Choice{ ChoiceId = 8, Text = "19", },
                                            new Choice{ ChoiceId = 9, Text = "600" },
                                        }
                      });
}

public ViewResult Survey()
{
    return View(questions[0]);
}

[HttpPost]
public ViewResult Survey(int QuestionId, int? ChoiceId, FormCollection formCollection)
{
    Question questionToBeDisplayed;
    if(!string.IsNullOrEmpty(formCollection["back"]))
    {
        questionToBeDisplayed = GetPreviousQuestion(QuestionId);
    }
    else
    {
        questionToBeDisplayed = GetNextQuestion(QuestionId);
    }
    return View(questionToBeDisplayed);
}

private Question GetPreviousQuestion(int questionId)
{
    // dummy implementation
    return questions[0];
}

private Question GetNextQuestion(int questionId)
{
    // dummy implementation; code below just gets the next question from the collection
    return questions.Where(q => q.QuestionId == questionId + 1).FirstOrDefault();
}

// my view
<% using (Html.BeginForm()) {%>

    <input name="QuestionId" id="QuestionId" type="hidden" value="<%= Html.Encode(Model.QuestionId) %>" />
    
    Question: <%= Html.Encode(Model.Text) %>
    <br />
    <ul>
    <% for (int i = 0; i < Model.Choices.Count; i++) { %>
        <li>
            <%= Html.RadioButton("ChoiceId", Model.Choices[i].ChoiceId) %> &nbsp; <%= Model.Choices[i].Text %>
        </li>
    <% } %>
    </ul>
    <input type="submit" id="back" name="back" value="<< Back" /> &nbsp;&nbsp;
    <input type="submit" id="next" name="next" value="Next >>" />
 <% } %>

Open in new window

0
 
LVL 27

Expert Comment

by:nmarun
ID: 33575902
To answer your concern in post 33575339, MVC cannot create a collection the way you are expecting. It's Model Binding logic is not very mature yet. You can create your own model binding logic to parse the posted html and create the collection, but this will quite complicated for what you're trying to do. Moreover, it is not needed that you get the collection. You just need to know what choice was selected for the particular question. This is just what my code is returning to you (see the [HttpPost] version of the Survey action method).

Arun
0
 
LVL 27

Assisted Solution

by:nmarun
nmarun earned 2000 total points
ID: 33575957
I'm experiencing intermittent power outage today so I'm responding in smaller parts.

Now coming to your questions in post 33575564.

>> So when I first load the questionnaire how would I know how to display the first question?
This would be done with whatever logic that you have to display the first question. See the code for the Survey action method:

public ViewResult Survey()
{
    // this is where you'll decide to get the first question from your database
    // I cannot comment on this as I'm not sure how your db is structured
}

The issue of Next question comes only when the user has answered the first one. So you do not need to call the GetNextQuestion() for the first question.

>> next or back button
Yes, that code is exactly for that purpose. Depending on what button the user clicks, the appropriate value will be populate in the FormCollection. So if the user clicks on the next button, then formCollection["next"] will have the value 'Next >>' and likewise.
0
 

Author Comment

by:ToString1
ID: 33576139
Excellent answers - you have more than earned your points.
I will be posting more questions about this survey app in the MVC zone later this afternoon

Thank you
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
IntroductionWhile developing web applications, a single page might contain many regions and each region might contain many number of controls with the capability to perform  postback. Many times you might need to perform some action on an ASP.NET po…
The purpose of this video is to demonstrate how to set up the WordPress backend so that each page automatically generates a Mailchimp signup form in the sidebar. This will be demonstrated using a Windows 8 PC. Tools Used are Photoshop, Awesome…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question