How to update partial view using jquery ajax

I wanted to give a quick but clear example how to use jQuery to update a partial view, an example which could be easy to replicate.

We need a model
The model consists of product class with three properties; a product code, name and price.

public class Product
{
    [Required]
    public string Code { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    [DataType(DataType.Currency)]
    public decimal UnitPrice { get; set; }
}

And a Controller
For simplicity there is no specific data layer or repository, the controller contains a global array of products. When a http post is made to the GetProducts ActionResult a parameter is passed specifying how many products to return.

public class HomeController : Controller
{
    private List<Product> products = new List<Product>() ;

    public HomeController()
    {
        products.Add(new Product { Code = "P001", Name = "Hair Dryer", UnitPrice = 10.50M });
        products.Add(new Product { Code = "P002", Name = "Carpet Cleaner", UnitPrice = 3.60M });
        products.Add(new Product { Code = "P003", Name = "Hair Remover", UnitPrice = 12.10M });
        products.Add(new Product { Code = "P004", Name = "Vacuum Cleaner", UnitPrice = 80.99M });
        products.Add(new Product { Code = "P005", Name = "Table", UnitPrice = 7.69M });
        products.Add(new Product { Code = "P006", Name = "Duvet Cover", UnitPrice = 12.89M });
        products.Add(new Product { Code = "P007", Name = "Towel", UnitPrice = 3.50M });
        products.Add(new Product { Code = "P008", Name = "Electric Oven", UnitPrice = 125.99M });
        products.Add(new Product { Code = "P009", Name = "Hair Straighteners", UnitPrice = 8.90M });
        products.Add(new Product { Code = "P010", Name = "Belt", UnitPrice = 3.50M });
    }

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult GetProducts(int quantity)
    {
        var selectedProducts = products.Take(quantity);
        return PartialView("_ProductList", selectedProducts);
    }
}

The Main View
mvcpartialviewupdate-main-view
Selecting from the dropdown list causes a change event the initiates the post to the server. If the post is successful the partial view is updated.
The date and time is displayed for comparison with the date and time on the partial view, they will be different.

<h2>Product Display</h2>
<div class="col-sm-6">
    @DateTime.Now.ToLongDateString()
    @DateTime.Now.ToLongTimeString()
<div class="panel panel-default">
<div class="panel-heading">
            Products</div>
<div class="panel-body">
<div class="form-group form-group-sm">
                <label class="control-label" for="PageSize">
                    How many products should be displayed?
                </label>
<div>
                    <select id="PageSize">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select></div>
</div>
<div id="SelectedProducts"></div>
</div>
</div>
</div>

jQuery AJAX
When a selection is made from the dropdown list the change event is triggered and a POST made to the server.

@section scripts{
    <script type="text/javascript">

        $(document).ready(function () {

            $("#PageSize").on("change", function () {
                var val = $('#PageSize').val();
                $.ajax({
                    url: "/Home/GetProducts",
                    type: "POST",
                    data: { quantity: val }
                })
                .done(function (partialView) {
                    $("#SelectedProducts").html(partialView);
                });
            });
        });
    </script>
}

And the Partial View (_ProductList.cshtml)
The partial view displays a list of products in a table. The POST date and time is displayed for comparison purposes.

@model IEnumerable<MVCUpdatePartial.Models.Product>
<div class="editor-label">
    Selected Products</div>
<table class="table">
    @foreach(var product in Model)
    {
<tr>
<td>@product.Code</td>
<td>@product.Name</td>
<td>@product.UnitPrice</td>
</tr>
}</table>
Updated: @DateTime.Now.ToLongDateString()
@DateTime.Now.ToLongTimeString()

After the POST
And how the view looks after the POST and the partial view is updated.
mvcpartialviewupdate-main-view-after-post

Javascript IntelliSense in Visual Studio

IntelleSense is a pretty standard feature of any modern Integrated Development Environment (IDE). Visual Studio has the ability to display IntelleSense not only for the whole .Net framework but also for any libraries included in the solution and any custom code written in C#, VB or similar language. IntelliSense is not available for javascript files by default, partly because javascript is not build by a compiler. Fortunately it is quite easy to configure.
Firstly, create a new file called _references.js in the ‘Script’ folder of your project (note the intended leading underscore). Then add a reference for each file you require IntelliSense for like below;

/// <reference path="jquery-2.1.1.js" />
/// <reference path="knockout-3.2.0.debug.js" />
/// <reference path="your-custom-file.js" />

There is a shortcut to typing the references manually, simply drag and drop the file from the Solution Explorer into the editor pane and the reference will be added for you.

That’s basically it. Simple but useful.

Using Configuration to Control When to Show Debug Javascript Alerts

It can sometimes be frustrating constantly changing alert messages when debugging javascript. One way around this is to read the debug setting from the web.config file.

<compilation debug="true" targetFramework="4.0" />

Create a variable in the javascript and initialise with the debug value.

var isDebug = ("@HttpContext.Current.IsDebuggingEnabled".toLowerCase() == 'true');

In the code at various places check the isDebug variable and display debug alerts as required, or some other action if needed.

if(isDebug)
{
    alert( // your message here );
}

When deployed to a production environment, presuming the debug setting is not there the alerts will not be displayed.

Differences Between $(document).ready and $(window).load

I am aware the differences between $(document).ready and $(window).load have been discussed numerous times already, maybe done to death in some circles. When I carried out my own investigation into these events I received different results in different browsers. From now on I will refer to document.ready and window.load rather than the full syntax.

Regarding document.ready

  • The event executes when the DOM is loaded. It is possible some elements i.e. images have not finished loading at that point.
  • They are additive so you can have multiple document.ready declarations on your page.
  • It works across platforms.

As for window.load

  • It is fired after the full page, including the images, has loaded.
  • Will fire after document).ready.

For the first tests I started off with a simple test page

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Page Test</title>
</head>
<body>
loaded
</body>
</html>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript">

    $(window).load() {
        alert("load");
    }

    $(document).ready() {
        alert("ready");
    }
</script>

When I loaded the page in IE8 and Chrome the alerts were displayed in the order they are in the code. So if window.load is first in code the “Load” alert will display first followed by the “ready” alert. If I swap the events around so the document.ready is first in code the “ready” alert will display first followed by the “Load” alert.

These results did not match my expectations. I decided to do more detailed tests with the page below.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Page Test</title>
</head>
<body>
Hello
</body>
</html>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
    $(window).load(function () {
        alert("window load fired!");
    });

    $(document).ready(function () {
        alert("second document ready fired!");
    });
</script>
<script>
    window.onload = function () {
        alert("javascript onload fired!");
    }

    $(document).ready(function () {
        alert("document ready fired!");
    });
</script>

I loaded the page in IE8, IE11 and Chrome. In all cases the document.ready events fired before the window load events.  Specifically they were fired in the following order.

second document ready fired!
document ready fired!
window load fired!
javascript onload fired!

Now if I change the order of the script blocks containing the events like so;

<script>
    window.onload = function () {
        alert("javascript onload fired!");
    }

    $(document).ready(function () {
        alert("document ready fired!");
    });
</script>
<script>
    $(window).load(function () {
        alert("window load fired!");
    });

    $(document).ready(function () {
        alert("second document ready fired!");
    });
</script>

The order which the events are fired changes slightly to;
document ready fired!
second document ready fired!
javascript onload fired!
window load fired!

Again the document.ready events fired before the window load events. For one final test with this page I moved the script blocks in to the head section. When the page loaded the results were the same.

At this point I felt the need to return to the simple page and carry out the first test again in the same browsers as before. The results were the same as before. The document.ready event was fired first when it was first in the code and the window.load event fired first when it was first in the code. I cannot explain why this is happening.

This demonstration has been helpful to me in understanding how the document.ready and window.load events work, and hopefully you have found it useful too.