SYLVIA LOBO
BUSINESS ENABLER
MVC4 FORM CHALLENGES
Submitting MVC form with Forms Collection
Decided to start blogging as inspired by a senior colleague!!
Was stuck in a seemingly simple task of posting a form with dynamic elements in MVC.
Task 1 - To create spinner using ace template
.js as below -
$('#StakeholdersForecast').each(function () {
$.ajaxSetup({ cache: false });
$(this).ajaxForm({
beforeSubmit: function (response) { },
success: function () {
$('.main-content').css('cursor', '');
$('.Forcast-Subcontainer').prepend('<div class="alert alert-success"><button type="button" class="close" data-dismiss="alert"><i class="ace-icon fa fa-times"></i></button>' +
'The forecast template has been saved</div>');
},
error: function (response) {
$('.Forcast-Subcontainer').prepend(response);
}
});
});
Task 2 - Main view containing 3 partial views -
Parent View -
@using (@Html.BeginForm("SubmitForecastedFigure", "Forcast", FormMethod.Post, new {id = "StakeholdersForecast"}))
{
<div class="portfolio-container">
<div class="Forcast-container">
<div class="row">
<div class="col-xs-12 col-sm-10">
<h2 class="page-header blue">
@Model.ForcastedYear
</h2>
</div>
@Html.Hidden("hdnPortfolioId", @Model.PortfolioId)
@Html.Hidden("hdnManagerId", @Model.ManagerId)
<div class="col-xs-12">
<div id="forcast-alerts-container"></div>
</div>
</div>
@}
Child View 1 -
<div class="course-group" data-group="@Model.CourseCategories[i].Name.Replace(" ", "-")">
<div class="course-category">
<div class="row">
<div class="col-xs-12 col-sm-6">@Model.CourseCategories[i].Name</div>
<div class="hidden-xs col-sm-1 column-label">CSF 5</div>
<div class="hidden-xs col-sm-2 column-label">Duration</div>
<div class="hidden-xs col-sm-3 column-label">Modality</div>
</div>
</div>
<div class="course-group-list">
@{
for (var j = 0; j < Model.CourseCategories[i].Courses.Count; j++)
{
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-@Model.CourseCategories[i].Courses[j].CourseId" onclick=" bindspinnerevt(@Model.CourseCategories[i].Courses[j].CourseId); ">
<div class="row course-row" data-courseid="1">
<div class="hidden-xs col-sm-1">
<i class="bigger-110 ace-icon fa fa-angle-right" data-icon-hide="ace-icon fa fa-angle-down" data-icon-show="ace-icon fa fa-angle-right"></i>
@Model.CourseCategories[i].Courses[j].Code
@if (@Model.CourseCategories[i].Courses[j].IsPilot)
{
<span><i class="ace-icon fa fa-asterisk orange"></i></span>
}
</div>
<div class="col-xs-12 col-sm-5">@Model.CourseCategories[i].Courses[j].Name</div>
<div class="hidden-xs col-sm-1">@Model.CourseCategories[i].Courses[j].CsfHours</div>
<div class="hidden-xs col-sm-2">@Model.CourseCategories[i].Courses[j].DurationNumber @Model.CourseCategories[i].Courses[j].DurationUnit</div>
<div class="hidden-xs col-sm-3">@Model.CourseCategories[i].Courses[j].Modality</div>
@Html.HiddenFor(m => Model.ManagerId, new {Value = @Model.ManagerId})
@Html.HiddenFor(m => Model.CourseCategories[i].Courses[j].ForecastedFiguresItem.ForecastedTemplateId, new {Value = Request.QueryString["forecastTemplateId"]})
@Html.HiddenFor(m => Model.CourseCategories[i].Courses[j].ForecastedFiguresItem.ForcastedPortfolioCourseId, new {Value = @Model.CourseCategories[i].Courses[j].PortfolioCourseId})
@Html.HiddenFor(m=>Model.CourseCategories[i].Courses[j].Name, new { Value = @Model.CourseCategories[i].Courses[j].Name })
@Html.HiddenFor(m=>Model.CourseCategories[i].Courses[j].ForecastedFiguresItem.ForcastedNumbers,new { Value = "1" } )
</div>
</a>
<div class="panel-collapse collapse in" id="collapse-@Model.CourseCategories[i].Courses[j].CourseId" >
<div class="panel-body">
@Html.Partial("ForecastedFigureRow", @Model.CourseCategories[i].Courses[j])
</div>
</div>
}
}
</div>
</div>
</div>
</div> *@
}
</div>
<div class="clearfix save-buttons">
<button type="button" class="btn btn-default pull-right btn-sm">
<i class="fa fa-close"></i>
Cancel
</button>
<button class="btn btn-primary pull-right btn-sm forecast-template-save" type="submit">
<i class="fa fa-save"></i>
Save
</button>
</div>
</div>
</div>
}
Child View 2 -
<div class="col-xs-12 col-sm-12">
<div id ="CourseGroup" class="profile-user-info profile-user-info-striped ">
@Html.HiddenFor(m=>m.CourseId, new {Name = string.Format("CourseCategories[{0}].Courses[{1}].CourseId", courseCategoriesIndex, courseIndex), id = "CourseId"})
@Html.HiddenFor(m => m.PortfolioCourseId, new { Name = string.Format("CourseCategories[{0}].Courses[{1}].PortfolioCourseId", courseCategoriesIndex, courseIndex), id = "PortfolioCourseId" })
@Html.HiddenFor(m => m.ForecastedFiguresItem.ForecastedTemplateId, new { Name = string.Format("CourseCategories[{0}].Courses[{1}].ForecastedFiguresItem.ForecastedTemplateId", courseCategoriesIndex, courseIndex), Value = Request.QueryString["forecastTemplateId"] })
@Html.HiddenFor(m => m.ForecastedFiguresItem.ForcastedFigureId, new { Name = string.Format("CourseCategories[{0}].Courses[{1}].ForecastedFiguresItem.ForcastedFigureId", courseCategoriesIndex, courseIndex), Value = Request.QueryString["forecastTemplateId"] })
@* @Html.Hidden("hdnCourseID", @Model.CourseId)
@Html.Hidden("hdnPortfolioCourseID", @Model.PortfolioCourseId)*@
<div class="profile-info-row col-xs-12 col-sm-3">
<div class="profile-info-name">Course</div>
<div class="profile-info-value">@Model.Name</div>
</div>
<div class="profile-info-row col-xs-12 col-sm-3">
<div class="profile-info-name">Forecasted No</div>
<div class="profile-info-value forcast-@Model.CourseId">
@Html.TextBoxFor(m => m.ForecastedFiguresItem.ForcastedNumbers, new { Name = string.Format("CourseCategories[{0}].Courses[{1}].ForecastedFiguresItem.ForcastedNumbers", courseCategoriesIndex, courseIndex), @id = "forecast-number-" + @Model.CourseId, @class = "input-sm forecast-number" })
</div>
</div>
<div class="profile-info-row col-xs-12 col-sm-3">
<div class="profile-info-name nomineeNameClass">Nominees</div>
<div class="profile-info-name"></div>
<table id="nominee-table-@Model.CourseId" class="table table-striped table-bordered table-hover" cellspacing="1" cellpadding="1">
<tbody>
</tbody>
</table>
</div>
Child View 3 -
<tr id="nomineeRow-@courseId-@foreCastedNo">
<td>
@Html.TextBox("NominatedEmployeeName-" + @courseId + "-" + @foreCastedNo, "", new { @id = "NominatedEmployeeName-" + @courseId + "-" + @foreCastedNo, @class = "input-sm form-field-tags" })
@* @Html.TextBoxFor(m=>Model.CourseCategories[foreCastedNo].Courses[foreCastedNo].ForecastedFiguresItem.NomineesList[foreCastedNo].NominatedEmployeeName,new{placeholder="Not decided", @id="NominatedEmployeeName-"+@courseId+"-"+@foreCastedNo, @class="input-sm form-field-tags" } )*@
</td>
<td>
@*<button onclick='removeNominee(this)' class="btn btn-default btn-xs pull-right" style="margin-left:5px;">*@
<i class='fa fa-times fa-lg red' rel='tooltip' title='Remove Nominee' onclick='removeNominee(@courseId,@foreCastedNo)' ></i>
@*</button>*@
</td>
</tr>
Task 3 - Controller for the partial views as above -
public ActionResult SubmitForecastedFigure(FormCollection collection, ForcastDetailEntity model)
{
var logic = new ForcastLogic();
if (model != null && model.CourseCategories != null)
{
foreach (var category in model.CourseCategories)
{
if (category.Courses != null)
{
foreach (var course in category.Courses)
{
if(course.ForecastedFiguresItem == null)
course.ForecastedFiguresItem = new ForcastDetailEntity.ForcastedFigureEntry();
if(course.ForecastedFiguresItem.NomineesList == null)
course.ForecastedFiguresItem.NomineesList = new List<ForcastDetailEntity.NomineesEntry>();
foreach (var nominies in collection.AllKeys.Where(x => x.Split('-').Count() > 1 && x.StartsWith("NominatedEmployeeName") && Convert.ToInt32(x.Split('-')[1]) == course.CourseId))
{
course.ForecastedFiguresItem.NomineesList.Add(new ForcastDetailEntity.NomineesEntry(){NominatedEmployeeName = collection[nominies]});
course.ForecastedFiguresItem.ForcastedPortfolioCourseId = course.PortfolioCourseId;
}
}
}
}
}
if (model.ManagerId == 0 || model.ManagerId == null)
{
model.ManagerId = Convert.ToInt64(collection["hdnManagerId"]);
}
logic.SaveForeCastedFigure(model);
return null;
//return Content(id.ToString());
}
Happy coding !!!