0

I have several buttons on a page. Each button loads a different partial "view" and uses the jQuery .load() method.

It works great but I noticed that if I keep clicking on this particular button, it keeps loading the partial view over and over until I stop. I am sure I could eventually crash the site (no good!).

I tried to cache it (by decorating the controller method and duration, etc) but it didn't work. I suspect that is because I am loading this view via button clicking.

How can I prevent repeating the load of this "view" without the user even knowing?

This is my jQuery/Javascript:

//"Select Area" button - click event
    $(".btnAreaDiv .btn-myClass").click(function () {

        switch (this.id) {
            case "btnMyButton":
                    $('#myDiv').load('_MyPartialView'); //to-do: only load me, if I haven't been loaded?
                break;
            //more code etc., more button handling
        }
    }

This is the contents of _MyPartialView.cshtml:

@{
    Layout = null;
}

<div class="row">
    <div class="col-md-6">
        <div class="row" style="width:97%">
            <div class="col-md-12" style="border:2px solid #c5c5c5"><span id="lblMySelector">My Selector</span></div>
        </div>
    </div>
    <div class="col-md-6"></div>
</div>

<div class="row nopadding checkboxDiv mySelector">
    <div class="col-md-12 nopadding">
        <input id="myCheckBox" type="checkbox" /><label for="myCheckBox">Include all/label> <br />
    </div>
</div>

And of course the ActionResult method in my controller:

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

I have tried this, but it didn't work:

switch (this.id) {
    case "btnMyButton":
        if (!$('#lblMySelector').length) {

            console.log('label not found', $('#lblMySelector').length);

            $('#myDiv').load('_MyPartialView'); 

        }
        break;
AussieJoe
  • 1,285
  • 1
  • 14
  • 29
  • 3
    Just have a `bool` variable as a flag to indicate if its been previously loaded (set to `true` when first loaded) –  Jun 26 '18 at 23:10
  • Yes, either a flag or check the content of `#myDiv` to see if it contains anything (assuming it's empty to start with) – DavidG Jun 26 '18 at 23:17
  • How are you getting to this switch? If it's some sort of "onclick" function, you could remove the event handling using [off](http://api.jquery.com/off/), or switch the "onclick" to use [one](http://api.jquery.com/one/), instead. – Tieson T. Jun 26 '18 at 23:20
  • @DavidG I would prefer to check the div. I can have many buttons on a page, and that would lead to many boolean flags. – AussieJoe Jun 26 '18 at 23:22
  • @TiesonT. the switch is in a click function. – AussieJoe Jun 26 '18 at 23:23
  • @StephenMuecke that was my original thought, but I am hesitant, as I could have MANY buttons and MANY flags. I need this to scale out for many buttons and views. – AussieJoe Jun 26 '18 at 23:24
  • @AussieJoe Can you update your example to include how you're binding to the click event? – Tieson T. Jun 26 '18 at 23:24
  • @TiesonT. done, thank you. – AussieJoe Jun 26 '18 at 23:27
  • 2
    @AussieJoe, You can maintain the flag as `data-isloaded="false"` attribute in the button (set to `true` when first loaded) –  Jun 26 '18 at 23:32
  • @StephenMuecke thats brilliant mate! – AussieJoe Jun 26 '18 at 23:33

3 Answers3

1

Let's assume you have some markup similar to this:

<button type="button" class="load-some-stuff" id="btnOne">One</button>
<button type="button" class="load-some-stuff" id="btnTwo">Two</button>
<button type="button" class="load-some-stuff" id="btnThree">Three</button>

And that you're doing something like this:

$(function(){

    $('.load-some-stuff').on('click', function(e){

        switch(this.id)
        {
            case 'btnOne':
                $('#some-container').load('example.com');
            break;

            case 'btnTwo':
                $('#some-container').load('example.com');
            break;

            case 'btnThree':
                $('#some-container').load('example.com');
            break;
        }

    });

});

If you don't want this to happen more than once, use off to remove the click event from the button:

$(function(){

    $('.load-some-stuff').on('click', function(e){
        // the current button
        var _this = $(this);

        switch(this.id)
        {
            case 'btnOne':
                $('#some-container').load('example.com', function(){
                    _this.off('click'); 
                });
            break;

            case 'btnTwo':
                $('#some-container').load('example.com', function(){
                    _this.off('click'); 
                });
            break;

            case 'btnThree':
                $('#some-container').load('example.com', function(){
                    _this.off('click'); 
                });
            break;
        }

    });

});

You could change where you use the off function; I placed it in the callback to load on the off chance that the load fails (the callback is only called for a successful response code).

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
  • It stops subsequent clicks, but how do I turn it back on? Like, if I start to press a different button after the initial one, how do I reset all the buttons (and remove the .off click)?? thank you! – AussieJoe Jun 27 '18 at 15:06
  • 1
    This would not work, in that case. "If you don't want this to happen more than once" was my assumption. – Tieson T. Jun 27 '18 at 18:49
1

You can disable button when clicked and enable when needed again (ex. when data was loaded). You can also set .data on clicked button to flag that was clicked and no more loading is needed.

    $(".btnAreaDiv .btn-myClass").click(function () {
    switch (this.id) {
        case "btnMyButton":
                if ($(this).data('loaded') == undefined) {
                    $(this).data('loaded', 1);
                    $('#myDiv').load('_MyPartialView');
                }
            break;
        //more code etc., more button handling
    }
}

you can also use .attr if you like ;)

arczinosek
  • 139
  • 5
  • If you load data to one container after clicks on many buttons, better option is to disable button to time when you receive data. – arczinosek Jun 26 '18 at 23:54
1

To cache data you can use .clone() method as like in this answer. You can make object to every possible request ex.

var cache = {};

and after receiving data store it into your cache var:

var cacher = function(name) {
    return function(response) {
        cache[name] = response;
    }
};

$("#myDiv").load('_MyPartialView', cacher('_MyPartialView'));
arczinosek
  • 139
  • 5
  • 1
    I think the best option could be to send header Cache-Control from backend. Browser should interpret it in ajax requests too and not making additional requests if not needed. – arczinosek Jun 27 '18 at 00:08