Reputation: 1674
I needed to have a View in my application that has 2 tabs. After struggling, I came up with the following with Bootstap Tabs and Partial Views:
<div id="tabs">
<ul class="nav nav-tabs">
<li class="active">
<a href="#OptinStatus" data-toggle="tab">Optin Status</a>
</li>
<li>
<a href="#OptiHistory" data-toggle="tab">Optin History</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="OptinStatus">
@Html.Partial("_OptinStatus")
</div>
<div class="tab-pane" id="OptiHistory">
@Html.Partial("_OptinHistory")
</div>
</div>
</div>
As long as I do this in my Results action, I can display the two tabs side by side and switch:
public ActionResult Results(OptinStatusViewModel viewModel)
{
// return RedirectToAction("OptInStatus");
return View();
}
The problem is now that I want to do some processing in the controller and display the results in the Partial View. so I switched the above to:
return RedirectToAction("OptInStatus");
That Action Method is supposed to be for the 1st partial view:
public ActionResult OptInStatus(OptinStatusViewModel viewModel)
{
HarmonyOperation harmonyoper = new HarmonyOperation();
ListProfileData res = new ListProfileData();
string listid = "60285206-7c9e-4af3-a0c4-0a69ec8d4bb4"; // Preferences Master List
string email = (string) TempData["User"];
string customerKey = Tools.GetCustomerKeyByEmail(email);
res = harmonyoper.GetProfileFromListByCustomerKey(listid, customerKey);
IDictionary<string, string> profileData = new Dictionary<string, string>();
// Found record in LIST for email
if (res != null)
{
profileData = Tools.ListKeyValueToDictionary(res.attributes);
//Check existence of this email
}
return View("_OptinStatus");
The problem when I do this is I get a new View that displays the "contents" of the Partial View instead of that Partial View in its tab. How can I get data to my partial view?
Upvotes: 1
Views: 6222
Reputation: 6271
You're returning a View from your controller, when you should be returning PartialView.
So instead of:
return View("_OptinStatus");
You do:
return PartialView("_OptinStatus", model); //model is not required
And you should get this model in the actual view "_OptinStatus", not in the "main view".
An example of using seperate partial models:
Controllers:
public ActionResult Results()
{
return View();
}
public ActionResult OptInStatus()
{
return PartialView("_OptinStatus");
}
... etc
Results-view:
<div class="tab-content">
<div class="tab-pane active" id="OptinStatus">
@Html.Action("_OptinStatus")
</div>
<div class="tab-pane" id="OptiHistory">
@Html.Action("_OptinHistory")
</div>
</div>
_OptinStatus-partialView:
@model OptinStatusModel
<div>My partial for Status</div>
_OptinHistory-partialView:
@model OptinHistoryModel
<div>My partial for History</div>
The same example using viewModel for both partials:
Controllers:
public ActionResult Results(OptinStatusViewModel viewModel)
{
return View("Results", viewModel);
}
Results-view:
@model OptinStatusViewModel
<div class="tab-content">
<div class="tab-pane active" id="OptinStatus">
@Html.Partial("_OptinStatus", Model.OptionStatusModel)
</div>
<div class="tab-pane" id="OptiHistory">
@Html.Partial("_OptinHistory", Model.OptionHistoryModel)
</div>
</div>
_OptinStatus-partialView:
@model OptinStatusModel
<div>My partial for Status</div>
_OptinHistory-partialView:
@model OptinHistoryModel
<div>My partial for History</div>
My prefered solution:
jQuery, included in _layouts
$(".partialContents").each(function(index, item) {
var url = $(item).data("url");
if (url && url.length > 0) {
$(item).load(url);
}
});
Now, instead of using Razor to render the views, you just use a div (and ajax through the code above):
<div class="partialContents" data-url="/Home/OptInStatus">
HomeController will get hit on action "OptInStatus".
Upvotes: 2