user2471435
user2471435

Reputation: 1674

MVC and Bootstrap Tabs - Can't display data in Partial View

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

Answers (1)

Mackan
Mackan

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

Related Questions