Home > OS >  MVC View data doesn't update on jQuery Post but does on Form submit button click
MVC View data doesn't update on jQuery Post but does on Form submit button click

Time:03-24

I have a DropDownListFor in my view that selects a date from a list of dates on the server. When I use a jQuery .on "change" $.post operation to post the date I select back to the controller, it correctly gets the updated data value from the server and updates the view model, but then it doesn't get displayed in the browser. It keeps the previous value instead. But if I click a submit button in the view's form instead, it correctly updates the data field with the data from the server. How I post the dropdown list selection determines whether my data field updates correctly or not.

Does anyone have any suggestions on how I can get the jQuery post to update my data field in the view instead of keeping the previous value ?

Here's my View Model:

    public class HtmlData
    {
        public string FileDateListSelection { get; set; }
        public List<SelectListItem> FileDateList { get; set; }
        public string ServerData { get; set; }

        public HtmlData(string selectedDate, List<SelectListItem> fileDateList, string serverData)
        {
            FileDateListSelection = selectedDate;
            FileDateList = fileDateList;
            ServerData = serverData;
        }
    }

Here's my View:

@model MvcJqueryTest.Models.HtmlData

@using (Html.BeginForm("SubmitButtonDateChange", "Home", FormMethod.Post, new { id = "dateSelectionForm" }))
{
    <div >
        <div >
            <div id="dateList">
                @Html.DropDownListFor(m => m.FileDateListSelection, Model.FileDateList)
            </div>
        </div>
        <div >
            <div id="buttons">
                <input type="submit" name="submit" value="Fetch" id="fetchButton" />
                <input type="submit" name="submit" value="Reset" id="resetButton" />
            </div>
        </div>
    </div>
}

<div >
    <div >
        <br />
        <h3>@Model.ServerData</h3>
        <br />
    </div>
</div>

<script type="text/javascript">
    $('#FileDateListSelection').on("change", function () {
        var menuDateSelected = $('#FileDateListSelection').val();
        $.post(
            '@Url.Action("JqueryDateChange", "Home")',
            { selectedDate: menuDateSelected },
            function (response) {
            }
        );
    });
</script>

Here's my Home Controller Methods:

        public ActionResult Index(string dateString)
        {
            DateTime compareTime = DateTime.Today;

            if (!string.IsNullOrEmpty(dateString))
                compareTime = DateTime.Parse(dateString);

            string quote = "Now is the winter of our discontent";

            if (compareTime < DateTime.Today)
                quote = "Made glorious summer by this sun of York";

            string selectedDate = FileOperations.GetDateList(compareTime, out List<SelectListItem> dateList);

            HtmlData hd = new HtmlData(selectedDate, dateList, quote);

            return View(hd);
        }

        [HttpPost]
        public ActionResult SubmitButtonDateChange(string FileDateListSelection, string submit)
        {
            string selectedDate = FileDateListSelection;

            if (submit.Equals("Reset", StringComparison.OrdinalIgnoreCase))
                selectedDate = DateTime.Now.Date.ToString("d", CultureInfo.GetCultureInfo("en-US"));

            return RedirectToAction("Index", "Home", new { dateString = selectedDate });
        }

        [HttpPost]
        public ActionResult JqueryDateChange(string selectedDate)
        {
            return RedirectToAction("Index", "Home", new { dateString = selectedDate });
        }

The GetDateList method just returns a SelectListItem list of dates of files in a folder for the dropdown list, and selects one date as the selected item in the list. If the selected date is before today, the h3 tag containing the view model's "ServerData" property in the view shows "Now is the winter of our discontent". If the selected date is after midnight today, the h3 tag shows "Made glorious summer by this sun of York".

When I change the selection in the dropdown list, the JqueryDateChange controller method executes, and does a RedirectToAction to the Index method with the selected date as a parameter, which fills in the view model with the correct data for the "ServerData" property. But the "ServerData" value in the model is not displayed in the browser. It always retains the previous value, even though I can see the correct value there in the debugger when I set a break on <h3>@Model.ServerData</h3> in the view.

When I click the Fetch or Reset buttons in the view's form, the SubmitButtonDateChange controller method executes, and also does a RedirectToAction to the Index method with the selected date as a parameter. That also fills in the view model with the correct value for the "ServerData" property, but then it is correctly updated in the browser, showing the new value based on the dropdown list selection.

I was originally using $.ajax to post the new dropdown list suggestion, but that had the same problem. I also tried moving the "@Model.ServerData" inside the Form's curly brackets, but that didn't help, either. I found some info about ModelState that I thought might help, but when I looked at it in the debugger, it only had one key/value pair for the dateString parameter, so I couldn't see how to use it to fix the problem.

CodePudding user response:

I think a AJAX solution would suffice to your scenario. You can do the following.

First, define a unique id for your HTML element, where you would show the value of ServerData:

<div >
    <div >
        <br />
        <h3 id="serverDataID">@Model.ServerData</h3>
        <br />
    </div>
</div>

Then you need to define your AJAX call like this:

<script type="text/javascript">
    $('#FileDateListSelection').on("change", function () {
        var menuDateSelected = $('#FileDateListSelection').val();
        
        var json = {
            menuDateSelected: menuDateSelected
        };

        var options = {};
        options.url = "@Url.Action("JqueryDateChange", "Home")";
        options.type = "POST";
        options.data = {"json": JSON.stringify(json)};
        options.dataType = "json";
        options.success = function (data) {
            if (data.status == "true") {
                $('#serverDataID').html(data.quoteString);
            }
            else {
                alert("Some Error");
            }
        };
        options.error = function (data) {
            alert("Error while calling function");
            console.log(data);
        };

        $.ajax(options);
    });
</script>

And your Controller method will return a JsonResult to handle the callback:

using System.Web.Script.Serialization;

[HttpPost]
public JsonResult JqueryDateChange(string json)
{
    var serializer = new JavaScriptSerializer();
    dynamic jsondata = serializer.Deserialize(json, typeof(object));
    //Get your variables here from AJAX call
    var dateString = Convert.ToString(jsondata["menuDateSelected"]);
    DateTime compareTime = DateTime.Today;

    if (!string.IsNullOrEmpty(dateString))
        compareTime = DateTime.Parse(dateString);

    string quote = "Now is the winter of our discontent";

    if (compareTime < DateTime.Today)
        quote = "Made glorious summer by this sun of York";

    string selectedDate = FileOperations.GetDateList(compareTime, out List<SelectListItem> dateList);   
    return Json(new { status = "true", quoteString = quote }, JsonRequestBehavior.AllowGet);
}
  • Related