Neil W
Neil W

Reputation: 9257

$(document).on('click' ... $.ajax call only executing once

I have a view (within the master _Layout.cshtml view) that has a child partial view.

I have button (class = get-widgets) on the main view that should make a call to the controller and retrieve some data to populate into the child partial view (_WidgetListPartial). This works fine ... once. The click event registration seems to lose itself after the first click and the 2nd and subsequent clicks do nothing.

I've also noticed that the data-loading-text is not appearing whilst the call runs (which has a thread.sleep(2000) to enforce a delay).

Code from the main view:

Index.cshtml

@model MyApp.Models.WidgetViewModels.MainWidgetViewModel

@{ ViewBag.Title = "Widget Control Panel"; }

<div class="jumbotron">
    <h1>@ViewBag.Title.</h1>
</div>

<div class="row">
    <div class="col-md-6">
        <h2>Widgets</h2>
        <button class="btn btn-default pull-right get-widgets" data-loading-text="Loading ...">Refresh</button><br />
        <div class="widgets">
            @{Html.RenderPartial("_WidgetListPartial", Model.Widgets);}
        </div>

        <p>@Html.ActionLink("Create Widget", "Create", "Widget")</p>
    </div>
</div>


<script type="text/javascript" src="@Url.Content("~/Scripts/jquery-1.10.2.js")"></script>
<script>
    $(document).ready(function () {
        $(document).on('click', '.get-widgets', function (e) {
            var $btn = $(this).prop('disabled', true);
            $.ajax('@Url.Action("GetWidgets", "Desktop")').done(function (html) {
                $('.widgets').html(html);
            }).always(function () {
                $btn.prop('disabled', false);
                alert('You pressed refresh ...');
            });
        });
    });
</script>

UPDATE **
After further analysis, it appears that the click event is actually firing. I have proven this by adding a javascript "alert" method within the function that is called (see above). So, it now appears that the real problem is that the "$.ajax( ..." call is not getting executed on second and subsequent clicks (UNLESS I clear the browser cache in between clicks).

So, my question now appears to be "Why would a "$.ajax" call fail (or be suppressed) based on the cache, when the $.ajax call does not actually know whether the data it needs to retrieve from the server is going to be different or not.

FINAL UPDATE and RESOLUTION

The reason for the problem appears to be that an ajax call will 'cache' if it is executed again with the exact same URL (which it does in my case because the variation in outcome is not based on the nature of the ajax call itself, but based on the fact that the underlying data repository may have changed state). The request from the ajax call is therefore identical from the browser's point of view.

The answer was to add $.ajaxSetup({ cache: false });

The full (working version) is below:

<script type="text/javascript" src="@Url.Content("~/Scripts/jquery-1.10.2.js")"></script>
<script>
    $.ajaxSetup({ cache: false });  // NEEDED TO ENSURE THE AJAX CALL WILL RUN ON EVERY CLICK, AND NOT JUST THE FIRST
    $(function () {
        $(document).on('click', '.get-widgets', function (e) {
            var $btn = $(this).prop('disabled', true);
            $.ajax('@Url.Action("GetWidgets", "Desktop")').done(function (html) {
                    $('.widgets').html(html);
                }).always(function () {
                    $btn.prop('disabled', false);
                });
            e.preventDefault();
        });
    });
</script>

Upvotes: 2

Views: 8559

Answers (1)

Ric
Ric

Reputation: 13248

Place your script inside jquery ready function:

$(function() {
    $(document).on('click', '.get-widgets', function (e) {
            var $btn = $(this).prop('disabled', true);
            $.ajax('@Url.Action("GetWidgets", "Desktop")').done(function (html) {
                $('.widgets').html(html);
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
});

also try adding this to ensure there is no caching being done:

$.ajax({
  url: "test.html",
  cache: false
})

Upvotes: 6

Related Questions