I'm having an issue with my Modal Pop-Up displaying incorrectly when it fails model validation on HttpPost. When the Modal returns data and it fails validation, I want the screen to return to having the modal popup display as a pop-up over the screen that generated the pop-up initially. What is happing is that the pop-up fills the entire screen, without ANY formatting (i.e. it is not a modal popup at this point). It does show the validation messages though, just as unformatted text. Here are all of the pieces of code that I use:
This is in my site.js
(function () {
// Initialize numeric spinner input boxes
//$(".numeric-spinner").spinedit();
// Initialize modal dialog
// attach modal-container bootstrap attributes to links with .modal-link class.
// when a link is clicked with these attributes, bootstrap will display the href content in a modal dialog.
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
// Attach listener to .modal-close-btn's so that when the button is pressed the modal dialog disappears
$('body').on('click', '.modal-close-btn', function () {
$('#modal-container').modal('hide');
});
//clear modal cache, so that new content can be loaded
$('#modal-container').on('hidden.bs.modal', function () {
$(this).removeData('bs.modal');
});
$('#CancelModal').on('click', function () {
return false;
});
});
This is how I call the pop-up:
<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-content"></div>
</div>
<a href="@Url.Action("CreateEdit", new { controller = "Issue", issueid = Model.IssueData.issueId, addedit = "add" })" class="modal-link btn btn-success">Add New Status</a>
This is the controller that handles the HttpPost from the Modal PopUp
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult CreateEdit(StatusViewModel model)
{
if (ModelState.IsValid)
{
//Do Stuff
return RedirectToAction("edit");
} else
{
return PartialView("_CreateEdit", model);
}
}
And here is the Modal-PopUp:
@model MYAPP.ViewModels.StatusViewModel
<!--Modal Body Start-->
<div class="modal-content">
<!--Modal Header Start-->
<div class="modal-header">
<h4 class="modal-title">@ViewBag.Title</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<!--Modal Header End-->
<form asp-action="CreateEdit" asp-controller="Issue" method="post" enctype="multipart/form-data">
@Html.AntiForgeryToken()
<div class="modal-body form-horizontal">
<div class="form-group row">
@Html.HiddenFor(model => model.addedit)
@Html.HiddenFor(model => model.IssueID)
@Html.HiddenFor(model => model.StatusDate)
@Html.LabelFor(model => model.Status, new { @class = "col-sm-2 col-form-label" })
<div class="col-sm-10">
<textarea asp-for="@Model.Status" class="form-control" rows="10" placeholder="Enter/Update Status">@Model.Status</textarea>
</div>
</div>
<div class="form-group row">
@Html.LabelFor(model => model.NextStep, new { @class = "col-sm-2 col-form-label" })
<div class="col-sm-10">
<textarea asp-for="@Model.NextStep" class="form-control" rows="10" placeholder="Please enter the next steps here">@Model.NextStep</textarea>
</div>
</div>
<div class="form-group">
<label asp-for="@Model.ColorCode" class="control-label"></label>
@Html.DropDownListFor(modelItem => modelItem.ColorCode, new[] {
new SelectListItem { Text = " ", Value = "" },
new SelectListItem { Text = "Red", Value = "R" },
new SelectListItem { Text = "Yellow", Value = "Y" },
new SelectListItem { Text = "Green", Value = "G" } })
<span asp-validation-for="@Model.ColorCode" class="text-danger"></span>
</div>
<div>
<table class="statustable">
<tr class="statustablerow">
<th></th>
<th>Previous Status</th>
<th>Previous Next Steps</th>
</tr>
<tr class="statustabledata">
@if (@ViewBag.LastColorCode == "R")
{
<td rowspan="2" width="2%" style=" background-color:red"></td>
}
else if (@ViewBag.LastColorCode == "Y")
{
<td rowspan="2" width="2%" style="background-color: yellow"></td>
}
else if (@ViewBag.LastColorCode == "G")
{
<td rowspan="2" width="2%" style="background-color: green"></td>
}
else
{
<td rowspan="2" width="2%" style="background-color: gray"></td>
}
<td width="20%">Previous Status:</td>
<td width="78%">@ViewBag.LastStatus</td>
</tr>
<tr class="statustabledata">
<td>Previous Next Steps:</td>
<td>@ViewBag.LastNextSteps</td>
</tr>
</table>
</div>
<!--Modal Footer Start-->
<div class="modal-footer">
<button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">Cancel</button>
<button class="btn btn-success relative" id="btnSubmit" data-save="modal">
<i class="loader"></i>
Submit
</button>
</div>
<div class="row">
</div>
<!--Modal Footer End-->
</form>
</div>
<script type="text/javascript">
$(function () {
});
</script>
<!--Modal Body End-->
How can I get the screen to revert to showing the page with the popup when validation fails?
You should submit the form via ajax and replace the modal with the returned data(html of the partialview), otherwise it will directly return the partialview as a new view.
I made some changes to your codes and you can refer to the below example:
Model:
public class StatusViewModel
{
public string addedit { get; set; }
public int IssueID { get; set; }
public DateTime StatusDate { get; set; }
[Required]
public string Status { get; set; }
[Required]
public string NextStep { get; set; }
[Required]
public string ColorCode { get; set; }
}
Edit.cshtml:
<div id="modal-container" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
</div>
</div>
</div>
<a href="@Url.Action("CreateEdit", new { controller = "Issue", issueid = "1", addedit = "add" })" class="modal-link btn btn-success">Add New Status</a>
@section scripts{
<script>
$('body').on('click', '.modal-link', function () {
var actionUrl = $(this).attr('href');
$.get(actionUrl).done(function (data) {
$('body').find('.modal-content').html(data);
});
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
$('body').on('click', '.relative', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
$('body').find('.modal-content').html(data);
});
})
$('body').on('click', '.close', function () {
$('body').find('#modal-container').modal('hide');
});
$('#CancelModal').on('click', function () {
return false;
});
</script>
}
_CreateEdit.cshtml:
@model StatusViewModel
<!--Modal Body Start-->
@{
ViewBag.Title = "Edit";
}
<div class="modal-header">
<h4 class="modal-title">@ViewBag.Title</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body form-horizontal">
<form asp-action="CreateEdit" asp-controller="Issue" method="post" enctype="multipart/form-data">
@Html.AntiForgeryToken()
<div class="form-group row">
@Html.HiddenFor(model => model.addedit)
@Html.HiddenFor(model => model.IssueID)
@Html.HiddenFor(model => model.StatusDate)
@Html.LabelFor(model => model.Status, new { @class = "col-sm-2 col-form-label" })
<div class="col-sm-10">
<textarea asp-for="@Model.Status" class="form-control" rows="10" placeholder="Enter/Update Status">@Model.Status</textarea>
<span asp-validation-for="@Model.Status" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
@Html.LabelFor(model => model.NextStep, new { @class = "col-sm-2 col-form-label" })
<div class="col-sm-10">
<textarea asp-for="@Model.NextStep" class="form-control" rows="10" placeholder="Please enter the next steps here">@Model.NextStep</textarea>
<span asp-validation-for="@Model.NextStep" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="@Model.ColorCode" class="control-label"></label>
@Html.DropDownListFor(modelItem => modelItem.ColorCode, new[] {
new SelectListItem { Text = " ", Value = "" },
new SelectListItem { Text = "Red", Value = "R" },
new SelectListItem { Text = "Yellow", Value = "Y" },
new SelectListItem { Text = "Green", Value = "G" } })
<span asp-validation-for="@Model.ColorCode" class="text-danger"></span>
</div>
<div>
<table class="statustable">
<tr class="statustablerow">
<th></th>
<th>Previous Status</th>
<th>Previous Next Steps</th>
</tr>
<tr class="statustabledata">
@if (@ViewBag.LastColorCode == "R")
{
<td rowspan="2" width="2%" style=" background-color:red"></td>
}
else if (@ViewBag.LastColorCode == "Y")
{
<td rowspan="2" width="2%" style="background-color: yellow"></td>
}
else if (@ViewBag.LastColorCode == "G")
{
<td rowspan="2" width="2%" style="background-color: green"></td>
}
else
{
<td rowspan="2" width="2%" style="background-color: gray"></td>
}
<td width="20%">Previous Status:</td>
<td width="78%">@ViewBag.LastStatus</td>
</tr>
<tr class="statustabledata">
<td>Previous Next Steps:</td>
<td>@ViewBag.LastNextSteps</td>
</tr>
</table>
</div>
<!--Modal Footer Start-->
<div class="modal-footer">
<button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">Cancel</button>
<input type="submit" class="btn btn-success relative" id="btnSubmit" data-save="modal" value="Submit">
</div>
<div class="row">
</div>
</form>
</div>
Controller:
public IActionResult Edit()
{
return View();
}
[HttpGet]
public ActionResult CreateEdit(int issueid, string addedit)
{
var model = new StatusViewModel
{
Status = "AAAAA",
NextStep = "BBBBB"
};
ViewBag.LastColorCode = "R";
ViewBag.LastStatus = "CCCC";
ViewBag.LastNextSteps = "DDDD";
return PartialView("_CreateEdit", model);
}
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult CreateEdit(StatusViewModel model)
{
if (ModelState.IsValid)
{
//Do Stuff
return RedirectToAction("edit");
}
else
{
return PartialView("_CreateEdit", model);
}
}
Result: