Reputation: 1127
I have a question concerning updating a partial view from another partial view where the first view is contained.
I have 4 dropdowns that are populated based on the previous selections, then the user may submit their selections and a database is queried and a table is populated based on their selections. I should note that I am very new to asp.net mvc and it's all still quite confusing to me.
Below is my code:
<form action="/Home/LoadRelease" method="post" style="text-align: center;">
@*Headers*@
<div id="BusinessAreaLabel" class="inline" style="width:14em;">Business Area</div>
<div id="GenericProjectLabel" class="inline" style="width:13em;">Generic Project</div>
<div id="ProjectLabel" class="inline" style="width:17em;">Project</div>
<div id="ReleaseLabel" class="inline" style="width:13em;">Release</div>
<br />
@*Dropdowns*@
<select id="BusinessAreaDropDown" name="BusinessArea" onchange="javascript: FillGenericProject(); FillProject(); FillReleases();" style="width: 13em;">
@Html.Partial(@"Dropdowns\_BusinessArea", Model.ProjectViewModels);
</select>
<select id="GenericProjectDropDown" name="GenericProject" onchange="javascript: FillProject(); FillReleases();" style="width: 13em;"></select>
<select id="ProjectDropDown" name="Project" style="width: 17em;" onchange="javascript: FillReleases();"></select>
<select id="ReleaseDropDown" name="Release" style="width: 13em;"></select>
<input type="submit" id="GoButton" style="visibility:hidden;" value="Go" />
</form>
<form id="ReleaseTableBody" style="text-align:center;">
@Html.Partial("_TableBody", Model.OpenCloseViewModels) //I want to update this.
</form>
<br />
and Home/LoadRelease:
[HttpPost]
public ActionResult LoadRelease(string Project, string Release)
{
var ProjectID = _ProblemReportsDB.ProjectMaps
.Where(r => r.Project == Project)
.Select(r => r.ID).FirstOrDefault();
ViewBag.Project = Project;
var Releases = from row in _ProblemReportsDB.PlannedOpenCloses
where (row.Project == ProjectID)
select row;
return PartialView("_TableBody", Releases.ToList());
}
The above loads the partial view "_TableBody", but actually directs to the page containing only the contents of _TableBody.
Ideally, I would remain on the page displaying and only update the _TableBody section of the page. I think I understand why it is currently failing, I'm telling it to run the action /Home/LoadRelease, which returns the _TableBody partial view, which it loads.
I'm having trouble figuring out how to make it only update the _TableBody partial view.
Thanks for any help you can offer.
EDIT:
Attempting Jasens method I have begun using an ajax function: Still loads to another page instead of updating the partial:
Code:
@using (Html.BeginForm("LoadRelease", "Home", FormMethod.Post, new { id = "DropDownForm", style="" }))
{
@*Headers*@
<div id="BusinessAreaLabel" class="inline" style="width:14em;">Business Area</div>
<div id="GenericProjectLabel" class="inline" style="width:13em;">Generic Project</div>
<div id="ProjectLabel" class="inline" style="width:17em;">Project</div>
<div id="ReleaseLabel" class="inline" style="width:13em;">Release</div>
<br />
@*Dropdowns*@
<select id="BusinessAreaDropDown" name="BusinessArea" onchange="javascript: FillGenericProject(); FillProject(); FillReleases();" style="width: 13em;">
@Html.Partial(@"Dropdowns\_BusinessArea", Model.ProjectViewModels);
</select>
<select id="GenericProjectDropDown" name="GenericProject" onchange="javascript: FillProject(); FillReleases();" style="width: 13em;"></select>
<select id="ProjectDropDown" name="Project" style="width: 17em;" onchange="javascript: FillReleases();"></select>
<select id="ReleaseDropDown" name="Release" style="width: 13em;"></select>
<button type="submit" id="GoButton" style="visibility:hidden;">Go</button>
}
@*</form>*@
<form id="ReleaseTableBody" style="text-align:center;">
@Html.Partial("_TableBody", Model.OpenCloseViewModels)
</form>
<br />
In index: (Parent of _DropDownBody):
<script src="~/Scripts/jquery-1.10.2.js">
$(document).ready(function () {
$("#DropDownForm").on("submit", function (event) {
event.preventDefault();
var form = $(this);
var Project = $('#ProjectDropDown').val();
var Release = $('#ReleaseDropDown').val();
alert(Project);
$.ajax({
url: form.attr("action"),
method: form.attr("method"),
data: form.serialize()
})
.done(function (result) {
$("#ReleaseTableBody").html(result);
});
});
});
</script>
Using A. Burak Erbora's method produces the same issue as well. Am I missing something?
Final edit: Jasen's answer worked and allowed me to update a partial view without redirecting. Still having issues getting the partial to show my content, but as far as the question goes - Jasen's answer works!
Upvotes: 0
Views: 6008
Reputation: 14250
Submitting a form will cause navigation. Since you want to stay on the same page you'll need to trap the submission event and use AJAX to update your page.
Main View
@using(Html.BeginForm("LoadRelease", "Home", FormMethod.Post, new { id = "DropDownForm", style = "" })
{
<!-- your drop down inputs -->
<button type="submit">Go</button>
}
<form id="ReleaseTableBody" style="text-align:center;">
@Html.Partial("_TableBody", Model.OpenCloseViewModels) //I want to update this.
</form>
Then the page script (don't forget to load jquery.js before this). Also note if you are embedding partial views you need to move this script "up" to the parent since @section
will not render in partials.
<script src="jquery.js"></script>
<script>
$(document).ready(function() {
$("#DropDownForm").on("submit", function(e) {
// prevent default submission
e.preventDefault();
// do AJAX post instead
var form = $(this);
$.ajax({
url: form.attr("action"),
method: form.attr("method"),
data: form.serialize()
})
.done(function(result) {
// replace content
$("#ReleaseTableBody").html(result);
});
});
}
</script>
Controller action unchanged
[HttpPost]
public ActionResult LoadRelease(string Project, string Release)
{
// search
return PartialView("_TableBody", results);
}
Upvotes: 3
Reputation: 1064
First off, I'd recommend you use html helpers. What you seem to need here is an ajax call instead of a standard form post. Instead of
<form action="/Home/LoadRelease" method="post" style="text-align: center;">
you can use
@using (Ajax.BeginForm("LoadRelease", "Home", options)){
@*Headers*@
<div id="BusinessAreaLabel" class="inline" style="width:14em;">Business Area</div>
<div id="GenericProjectLabel" class="inline" style="width:13em;">Generic Project</div>
<div id="ProjectLabel" class="inline" style="width:17em;">Project</div>
<div id="ReleaseLabel" class="inline" style="width:13em;">Release</div>
<br />
@*Dropdowns*@
<select id="BusinessAreaDropDown" name="BusinessArea" onchange="javascript: FillGenericProject(); FillProject(); FillReleases();" style="width: 13em;">
@Html.Partial(@"Dropdowns\_BusinessArea", Model.ProjectViewModels);
</select>
<select id="GenericProjectDropDown" name="GenericProject" onchange="javascript: FillProject(); FillReleases();" style="width: 13em;"></select>
<select id="ProjectDropDown" name="Project" style="width: 17em;" onchange="javascript: FillReleases();"></select>
<select id="ReleaseDropDown" name="Release" style="width: 13em;"></select>
<input type="submit" id="GoButton" style="visibility:hidden;" value="Go" />
}
and somewhere in your html you have:
<div id="ReleaseTableBody">
@Html.Partial(_TableBody", Model.OpenCloseViewModels)
</div>
you will need to define the options
object for the Ajax helper like:
var options = new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "ReleaseTableBody",
OnBegin = "OnCallbackBegin",
OnFailure = "OnCallbackFailure",
OnSuccess = "OnCallbackSuccess",
LoadingElementId = "loading"
};
you can also use the event callback methods if you define their JavaScript functions like:
<script>
function OnCallbackBegin() {
$(".btn-loading-icon").show();
$(".btn-loading-text").hide();
}
function OnCallbackSuccess(data) {
//alert("onSuccess: result = " + data.result);
$(".btn-loading-icon").hide();
$(".btn-loading-text").show();
SomeOtherFunction();
}
I would also advise using the @Html.DropdownFor
helper for your dropdowns.
Upvotes: 1