Wizard built using the PopupForm



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 submitting 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 submitted inside of it, and make it an ajax request).

WizardDemo/Index.cshtml
@(Html.Awe().InitPopupForm(new PopupFormOpt
{
Name = "wizard1",
Url = Url.Action("StartWizard"),
OnSuccess = "wizardFinish",
UseDefaultButtons = false,
Modal = true
}))

<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) {
awe.flash(awem.notif(res.Message));
}
</script>
Demos/Misc/WizardDemoController.cs
using AweCoreDemo.Data;
using AweCoreDemo.Models;
using AweCoreDemo.Utils;
using AweCoreDemo.ViewModels.Input.Wizard;
using Microsoft.AspNetCore.Mvc;

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

public IActionResult 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 IActionResult WizardStep1(string wizardId)
{
var wiz = Cache.Get(wizardId);

Check.NotNull(wiz, "wizard");
var model = (WizardModel)wiz;

return PartialView(model.Step1);
}

[HttpPost]
public IActionResult WizardStep1(Step1Model step1Model)
{
if (!ModelState.IsValid)
{
return PartialView(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 IActionResult WizardStep2(string wizardId)
{
var wiz = Cache.Get(wizardId);

Check.NotNull(wiz, "wizard");
var model = (WizardModel)wiz;

return PartialView(model.Step2);
}

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

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

wizardModel.Step2 = step2Model;

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

public IActionResult 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 IActionResult 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 AweCoreDemo.ViewModels.Input.Wizard.Step1Model
<div class="wizardForm">
<div id="wizardData" style="height: 250px;">
@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;">
<button type="submit" class="awe-btn mbtn" onclick="$('#wizardData form').submit()" style="width: 100px;">Continue</button>
</div>
</div>
WizardDemo/WizardStep2.cshtml
@model AweCoreDemo.ViewModels.Input.Wizard.Step2Model
<div class="wizardForm">
<div id="wizardData" style="height: 250px;">
@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))
{
<button type="submit" class="awe-btn mbtn" style="width: 100px;">Go back</button>
}
</div>

<div style="text-align: center;">
<button type="submit" class="awe-btn mbtn" onclick="$('#wizardData form').submit()" style="width: 100px;">Continue</button>
</div>
</div>
</div>
WizardDemo/WizardFinish.cshtml
@model AweCoreDemo.ViewModels.Input.Wizard.WizardFinishModel
<div class="wizardForm">
<div id="wizardData" style="height: 250px;">
@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))
{
<button type="submit" class="awe-btn mbtn" style="width: 100px;">Go back</button>
}
</div>

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



Comments