Chris V.
Chris V.

Reputation: 1143

Post to an action which returns a partial view in the original page : MVC

I'm working on a single page web app. The page has a dropdown list. When an item is selected, I use jQuery to post the selected value to an action method, which [for now, for testing purposes] adds that value to the ViewBag, and returns a PartialView. I want to put this partial view in the same page, obviously. So when I select a value from the dropdown, the selected option should show up below it. Is this possible or am I approaching this the wrong way?

Relevant code for context:

Index (Main page)

<html>
    @using SampleTracking.Models.ViewModels;
    @model SamplingEventsVM

    <head>
        <title>@ViewBag.Title</title>
        <script src="~/Scripts/jquery-2.1.1.js"></script>
        <script type="text/javascript" src="~/Scripts/CustomScripts.js"></script>

    </head>

    <body>
        <span id="SamplingEventDiv">
            @Html.DropDownListFor(model => model.SelectedSamplingEvent, Model.SamplingEvents, new { @id = "SamplingEventSelection" })
        </span>
        <div id="SampleListDiv">
            @{Html.RenderPartial("~/Views/Home/RetrieveSamples.cshtml");}
        </div>
    </body>
</html>

Script

$(function (ready) {
    $("#SamplingEventSelection").change(
            function () {
                $.post(
                    "/Home/RetrieveSamples",
                    { selectedSamplingEvent: $("#SamplingEventSelection").val() },
                    function (data) {
                        $("#SamplingEventDetails").html(data)
                    }
                )
            }
        )
});

Action method script is posting to

public ActionResult RetrieveSamples(string samplingEvent)
{
    ViewBag.Selected = samplingEvent;

    return PartialView();
}

Partial view

<div id="SamplingEventDetails" style="margin-top:100px;">@ViewBag.Selected</div>

Upvotes: 0

Views: 4710

Answers (2)

magos
magos

Reputation: 3511

Yes, it is. You have to use Ajax for that purpose.

There is Ajax.BeginForm helper. Your view should look like below:

@using (Ajax.BeginForm(new AjaxOptions() { LoadingElementId="loadingPanel", UpdateTargetId = "info", InsertionMode = InsertionMode.InsertBefore, Url = Url.Action("AjaxTest")}))
  {
    @Html.DropDownList("dropDown1", new SelectList(new[] { "One", "Two", "Three"}));    
    <br /><br />
    <input type="submit" value="Send" />
  }

Upvotes: 1

xDaevax
xDaevax

Reputation: 2022

Consider loading only the data instead of the html for a partial view.

Using Ajax requests with MVC is really useful, and you're not limited to partial views either. You can return JSON data as well if you didn't want to return a view.

public ActionResult RetrieveSamples(string samplingEvent) {
    JsonResult result = new JsonResult();

    result.Data = samplingEvent;
    return result;
} // end function RetrieveSamples

Then in your JS:

function (data) {
    console.log("Json Data returned: " + data);
    $("#SamplingEventDetails").html(data);
}

Edit: Here is a working solution I have:

Controller:

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
    //
    // GET: /Home/

        public ActionResult Index()
        {
            List<SelectListItem> items = new List<SelectListItem>();
            items.Add(new SelectListItem() { Text = "Option 1", Value = "1" });
            items.Add(new SelectListItem() { Text = "Option 2", Value = "2" });

            ViewBag.Options = items;
            return View("Index");
        }

        public ActionResult getDetail(string selectedSamplingEvent) {
            JsonResult result = new JsonResult();
            result.Data = selectedSamplingEvent;

            return result;
        }

    }
}

Full view (Index.cshtml)

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@Html.DropDownList("Options")

<div class="dynamic-wrapper">
    @Html.Partial("Details")
</div>

<script type="text/javascript">

$(document).ready(function () {
    $("#Options").change(function (e) {
        $.post(
            "home/getDetail",
            { selectedSamplingEvent: $("#Options").val() },
            function (data) {
                $("#SamplingEventDetails").html(data);
            }

        );
    });
});
</script>

Partial view:

<div id="SamplingEventDetails"><!-- Data will go here --></div>

Upvotes: 1

Related Questions