/
How to implement the "Step Wizard"
How to implement the "Step Wizard"
Create: /models/WizardStepViewModel.cs
using System;
namespace {service}.Web.Portal.Models
{
public enum WizardStepState
{
NotAccessed,
Completed,
Incomplete,
InProgress,
Inapplicable,
Summary
}
public class WizardStepViewModel
{
public string Title { get; set; }
public string Url { get; set; }
public WizardStepState State { get; set; }
public string GetUrl()
{
return State == WizardStepState.Inapplicable ||
State == WizardStepState.NotAccessed
? null
: Url;
}
}
}
Create: /models/WizardViewModel.cs
using System.Collections.Generic;
using System.Linq;
namespace {service}.Web.Portal.Models
{
public class WizardViewModel
{
public WizardViewModel()
{
WizardSteps = new List<WizardStepViewModel>();
}
public ICollection<WizardStepViewModel> WizardSteps { get; set; }
public int Count => WizardSteps.Count;
public int? LastCompletedIndex => WizardSteps.Reverse()
.Select((x,i) => new {State = x.State, Index = Count - i - 1})
.FirstOrDefault(x=>x.State == WizardStepState.Completed)
?.Index;
public int? InProgressIndex => WizardSteps.Reverse()
.Select((x, i) => new { State = x.State, Index = Count - i - 1})
.FirstOrDefault(x => x.State == WizardStepState.InProgress)
?.Index;
}
}
Create: /views/shared/wizard.cshtml
@using {service}.Web.Portal.Models
@model {service}.Web.Portal.Models.WizardViewModel
<!--From: https://bootsnipp.com/user/snippets/aRlN3 -->
@functions {
int CalculateConnectingLineWidth(WizardViewModel wizard)
{
int[] lineMap = { -1, -1, 48, 69, 79, 80, 80, 84, 84, 91, 91 };
return wizard.Count <= 10 ? lineMap[Model.WizardSteps.Count] : 100;
}
int CalculateCompletionLineStartingPosition(WizardViewModel wizard)
{
int[] lineMap = { -1, -1, 27, 15, 11, 9, 9, 9, 8, 7, 7 };
return wizard.Count <= 10 ? lineMap[Model.WizardSteps.Count] : 178;
}
int CalculateCompletionLineWidth(WizardViewModel wizard)
{
var inProgressIndex = wizard.InProgressIndex;
var lastCompletedIndex = wizard.LastCompletedIndex;
if (!inProgressIndex.HasValue && !lastCompletedIndex.HasValue)
{
return 0;
}
// in case the inProgress index hasn't been defined, use the lastCompleted index
int index = inProgressIndex.HasValue
? inProgressIndex.Value
: lastCompletedIndex.GetValueOrDefault();
if (index == 0)
{
return 0;
}
int fullWidth = CalculateConnectingLineWidth(wizard);
int singleWidth = fullWidth / (wizard.Count - 1);
return singleWidth * index;
}
}
<style>
@@media screen and ( max-width : 585px ) {
.app-name-submenu {
font-size: 25px;
}
}
.wizard .nav-tabs > li {
width: @(100 / Model.WizardSteps.Count)%;
}
.connecting-line {
width: @CalculateConnectingLineWidth(Model)%;
}
.completion-line {
width: @CalculateCompletionLineWidth(Model)%;
left: @CalculateCompletionLineStartingPosition(Model)%;
}
</style>
<div class="row">
<section>
<div class="wizard">
<div class="wizard-inner">
<div class="completion-line"></div>
<div class="connecting-line"></div>
<ul class="nav nav-tabs">
@{
int counter = 1;
}
@foreach (var wizardStep in Model.WizardSteps)
{
<li role="presentation" class="@(wizardStep.State == WizardStepState.InProgress ? "active": "")@(wizardStep.State == WizardStepState.Completed ? "completed": "")">
<p class="step-label-top">Step @counter</p>
<a @Html.Raw(wizardStep.GetUrl() != null ? string.Format("href=\"{0}\"", wizardStep.GetUrl()) : "") aria-label="step@count">
<span class="round-tab@(wizardStep.GetUrl()==null?"":" pointer")">
@if (counter != Model.Count)
{
switch (wizardStep.State)
{
case WizardStepState.NotAccessed:
<i class="fa fa-file-text"></i>
break;
case WizardStepState.Completed:
<i class="fa fa-check fa-lg"></i>
break;
case WizardStepState.Incomplete:
<i class="fa fa-exclamation-triangle fa-lg"></i>
break;
case WizardStepState.InProgress:
<i class="fa fa-file-text fa-lg bg-white"></i>
break;
case WizardStepState.Inapplicable:
<i class="fa fa-minus fa-lg"></i>
break;
case WizardStepState.Summary:
<i class="fa fa-print fa-lg"></i>
break;
default:
throw new ArgumentOutOfRangeException();
}
}
else
{
<i class="fa fa-paper-plane fa-lg"></i>
}
</span>
</a>
<div style="width:100%">
<div class="step-label-bottom">@wizardStep.Title</div>
</div>
</li>
counter++;
}
</ul>
</div>
</div>
</section>
</div>
Create: /content/css/wizard.css
Edit: /App_Start/BundleConfig.cs
Paste:
Edit your base controller and add:
Find the BaseModel for the Step’s view model:
Add the following property to the BaseModel:
Edit each affected page controller method
(e.g. public ActionResult Step1Page(int id))
Locate the viewmodel, and add:
Edit each affected view(cshtml)
Paste:
Edit _Layout{service}.cshtml
Output the stylesheet:
Render the Wizard, e.g.
, multiple selections available,
Related content
Collecting submitted form data, and storing it in MTOA
Collecting submitted form data, and storing it in MTOA
More like this
Create, Read, Update, Submit of Service Requests Using API
Create, Read, Update, Submit of Service Requests Using API
Read with this
Pattern: Form Wizard Step
Pattern: Form Wizard Step
More like this
MTOA API
MTOA API
Read with this
FormBuilder Admin UI - Walkthrough
FormBuilder Admin UI - Walkthrough
More like this
MTOA Web Service Framework
MTOA Web Service Framework
Read with this