2

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>
Cœur
  • 37,241
  • 25
  • 195
  • 267
Neil W
  • 7,670
  • 3
  • 28
  • 41
  • See if you get any console log errors – karthikr Oct 30 '13 at 18:22
  • 1
    I may be mistaken but you don't appear to have wrapped the $(document).On() in the ready function such as found here: http://stackoverflow.com/questions/17605296/document-onclick-not-working – Ric Oct 30 '13 at 18:27

1 Answers1

6

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
})
Ric
  • 12,855
  • 3
  • 30
  • 36
  • Thanks for the suggestion. I've wrapped it in "$(document).ready(function() { ***original script *** });", and have also tried it without the "(document).ready" as per your suggested answer here. However, the symptoms persist. ALSO ... I've noticed that if I hit the browser refresh button, the page is presented without the data (that is retrieved by the refresh command), and when I click refresh now the data is re-displayed ... BUT ... it re-displays it *instantly* and does not appear to have executed the GetWidgets command on the Desktop Controller!!! – Neil W Oct 30 '13 at 18:44
  • Excuse my ignorance, but are you talking about the "Output" window within Visual Studio when you (and @kartikhr) talk about "console log errors"? – Neil W Oct 30 '13 at 18:55
  • most browsers have a console and other diagnostic info at your disposal. chrome allows you to get there by pressing F12, and safari has some info here: https://developer.mozilla.org/en-US/docs/Tools/Web_Console you could also install firebug to view it i think. IE i believe you can also press F12 and view the console and it is from there you can see any issues and errors being raised (if any) – Ric Oct 30 '13 at 19:05
  • OK. Thanks for the pointer. I've used the F12 tools on IE and the "Console" tab does not report any errors. However, whilst in there, I noticed a "cache" menu option. I chose to clear the browser cache, and then hit the "Refresh" button on my page again. TA-DA! This time the event fired. To be clear, I went through the following steps: 1) Load the page. 2) Hit the Refresh Command button (not browser refresh) 3) Everything worked. 4) Hit the Refresh Command ... NOTHING 5) Cleared cache (without refreshing the page) 6) Hit the Refresh Command ... BINGO So ... what does this tell me? – Neil W Oct 30 '13 at 19:16
  • have a look here and notice the cache: false options in the ajax call, see if that helps.. http://api.jquery.com/jQuery.ajax/ – Ric Oct 30 '13 at 19:35
  • Sorted. Many thanks!!!! $.ajaxSetup({ cache: false }); was the answer. Original question updated. – Neil W Oct 30 '13 at 19:56