Wizard Demo



In this demo a Wizard is built using the PopupForm helper. We're not using the default Ok and Cancel buttons instead a submit button is placed on the bottom center of the form.
Stepping forward is done by submiting the form, the successful submit will redirect to another action which will return a view (html), when the popupform receives html/string it replaces its content with that html.
Stepping back is performed by submitting a separate form to the needed step, the form uses method get. (The popup form will handle any form that is being submited inside of it, and make it an ajax request).

WizardDemo/Index.cshtml
@(Html.Awe().InitPopupForm()
.Name("wizard1")
.Url(Url.Action("StartWizard"))
.Success("wizardFinish")
.UseDefaultButtons(false)
.Modal())
<button type="button" onclick="awe.open('wizard1')" class="awe-btn mbtn">click here to start wizard</button>
<br />
<br />
<script type="text/javascript">
function wizardFinish(res) {
alert(res.Message);
}
</script>
Demos/Misc/WizardDemoController.cs
using System;
using System.Linq;
using System.Web.Mvc;

using AwesomeMvcDemo.Models;
using AwesomeMvcDemo.ViewModels.Input.Wizard;

namespace AwesomeMvcDemo.Controllers.Demos.Misc
{
public class WizardDemoController : Controller
{
public ActionResult Index()
{
return View();
}

public ActionResult StartWizard()
{
var wizardModel = new WizardModel { Id = Guid.NewGuid().ToString() };
wizardModel.Step1 = new Step1Model { WizardId = wizardModel.Id };
wizardModel.Step2 = new Step2Model { WizardId = wizardModel.Id };

Cache.Set(wizardModel.Id, wizardModel);

return RedirectToAction("WizardStep1", new { WizardId = wizardModel.Id });
}

public ActionResult WizardStep1(string wizardId)
{
var model = (WizardModel)Cache.Get(wizardId);

return PartialView(model.Step1);
}

[HttpPost]
public ActionResult WizardStep1(Step1Model step1Model)
{
if (!ModelState.IsValid)
{
return View(step1Model);
}

//all good
//set model for step1 and redirect to step2
var wizardModel = (WizardModel)Cache.Get(step1Model.WizardId);
wizardModel.Step1 = step1Model;

var oldCategoryId = wizardModel.Step2.CategoryId;

//set category for next step
wizardModel.Step2.CategoryId = step1Model.CategoryId.Value;

//clear selected meals when we go gack from Step2 to Step1 and change the category
if (oldCategoryId != 0 && wizardModel.Step2.CategoryId != oldCategoryId)
{
wizardModel.Step2.MealIds = null;
}

//go to next step
return RedirectToAction("WizardStep2", new { WizardId = wizardModel.Id });
}

public ActionResult WizardStep2(string wizardId)
{
var model = (WizardModel)Cache.Get(wizardId);

return PartialView(model.Step2);
}

[HttpPost]
public ActionResult WizardStep2(Step2Model step2Model)
{
var wizardModel = (WizardModel)Cache.Get(step2Model.WizardId);
step2Model.CategoryId = wizardModel.Step2.CategoryId;

if (!ModelState.IsValid)
{
return View(step2Model);
}

wizardModel.Step2 = step2Model;

return RedirectToAction("WizardFinish", new { WizardId = wizardModel.Id });
}

public ActionResult WizardFinish(string wizardId)
{
var model = (WizardModel)Cache.Get(wizardId);
var finishModel = new WizardFinishModel();

finishModel.WizardId = model.Id;
finishModel.Name = model.Step1.Name;

var category = Db.Categories.SingleOrDefault(o => o.Id == model.Step1.CategoryId);
if (category != null)
{
finishModel.Category = category.Name;
}

finishModel.Meals = Db.Meals.Where(o => model.Step2.MealIds.Contains(o.Id)).Select(o => o.Name).ToArray();

return PartialView(finishModel);
}

[HttpPost]
public ActionResult WizardFinish(WizardConfirmModel confirmModel)
{
//wizard input confirmed
var model = (WizardModel)Cache.Get(confirmModel.WizardId);

//do something with model

//clear session
Cache.Remove(model.Id);
var meals = Db.Meals.Where(o => model.Step2.MealIds.Contains(o.Id)).Select(o => o.Name).ToArray();

return Json(new { Message = string.Format("Thank you {0} with meals: {1} was saved", model.Step1.Name, string.Join(",", meals)) });
}
}
}
WizardDemo/WizardStep1.cshtml
@model AwesomeMvcDemo.ViewModels.Input.Wizard.Step1Model
<div class="wizardForm">
<div id="wizardData" style="height: 200px;">
@using (Html.BeginForm())
{
<div class="expl">Hi, please write a name and select a category </div>

@Html.EditorFor(o => o.Name)
@Html.EditorFor(o => o.CategoryId)
}
</div>
<div style="text-align: center;">
<input type="submit" value="Continue" class="awe-btn mbtn" onclick="$('#wizardData form').submit()" style="width: 100px;" />
</div>
</div>
WizardDemo/WizardStep2.cshtml
@model AwesomeMvcDemo.ViewModels.Input.Wizard.Step2Model
<div class="wizardForm">
<div id="wizardData" style="height: 200px;">
@using (Html.BeginForm())
{
<div>good, now select a meal</div>

@Html.EditorFor(o => o.CategoryId)
@Html.EditorFor(o => o.MealIds)
}
</div>
<div>
<div style="float: left; margin-right: -100px;">
@using (Html.BeginForm("WizardStep1", null, new { Model.WizardId }, FormMethod.Get))
{
<input type="submit" value="Go back" class="awe-btn mbtn" style="width: 100px;" />
}
</div>

<div style="text-align: center;">
<input type="submit" value="Continue" class="awe-btn mbtn" onclick="$('#wizardData form').submit()" style="width: 100px;" />
</div>
</div>
</div>
WizardDemo/WizardFinish.cshtml
@model AwesomeMvcDemo.ViewModels.Input.Wizard.WizardFinishModel
<div class="wizardForm">
<div id="wizardData" style="height: 200px;">
@using (Html.BeginForm())
{
@Html.HiddenFor(o => o.WizardId)
<text>Name :</text> @Model.Name <br />
<text>Category:</text> @Model.Category <br />
<text>Meals:</text> @(string.Join(",", Model.Meals))
}
</div>

<div>
<div style="float: left; margin-right: -100px;">
@using (Html.BeginForm("WizardStep2", null, new { Model.WizardId }, FormMethod.Get))
{
<input type="submit" value="Go back" class="awe-btn mbtn" style="width: 100px;" />
}
</div>

<div style="text-align: center;">
<input type="submit" value="Finish" class="awe-btn mbtn" onclick="$('#wizardData form').submit()" style="width: 100px;" />
</div>
</div>
</div>