1

I have an asp.net page that returns a partial view in the tab I am currently doing my work in. I have the jQuery all set up and it works. It works one time and through ajax returns a partial view .html(result);

However this only works one time. I click the button it does everything behind the scenes like it should, it replaces the html like it should. Then when I click the button again nothing, its like the jQuery doesn't exist for these buttons any more. There is no page reload this is all done through ajax.

the HTML that is used when the page first is loaded and the HTML returned through .html(result) is the exact same html same partial view is used for both.

Is my jQuery somehow being disconnected when this partial view is returned?

Here is my Ajax call:

function updateSort(object) {
    jQuery.ajax({
        url: "/MasterList/UpdateSort",
        type: "get",
        data: object, //if you need to post Model data, use this
        success: function (result) {
            //alert('success');
            //console.log(result);
            jQuery("#procedures").html(result);
        }
    });
}

Here is the button click:

jQuery(".btnMoveUp").click(function () {
        var $this = jQuery(this),
            processID = $this.data('processid'),
            currProcedureID = $this.data('procedureid'),
            currSortOrder = $this.data('sortorder'),
            idx = jQuery('.commentlist li').index($this.closest('li')),
            $prevLi = jQuery('.commentlist li').eq(idx - 1),
            $anchor = $prevLi.find('.btnContainer a'),
            prevProcedureID = $anchor.data('procedureid'),
            prevSortOrder = $anchor.data('sortorder');

        // create object that we can pass to MVC controller
        var objProcedure = {};

        objProcedure = {
            _processID: processID,
            _currProcedureID: currProcedureID,
            _currSortOrder: currSortOrder,
            _switchProcedureID: prevProcedureID,
            _switchSortOrder: prevSortOrder
        }

        updateSort(objProcedure);

    });

Why would this work only a single time?

James Wilson
  • 5,074
  • 16
  • 63
  • 122
  • If the elements with event handlers bound to them are in the html that is replaced, then yes, you lose those bindings. Either rebind after you load the new html, or use event delegation. – Jason P Sep 12 '13 at 15:44
  • 1
    I'm guessing you're replacing the elements with new elements, and even if the markup is exactly the same, the elements are not, and the event handlers will be lost. What you need is event delegation. – adeneo Sep 12 '13 at 15:46
  • @adeneo yes the entire div is being replaced with the new results from the partial view. – James Wilson Sep 12 '13 at 15:54
  • @Adeneo I tried to change my jQuery to use .on('click' but that didn't seem to fix anything. Is that what I am missing? or do I really have to rebind them in my Ajax success portion? Seems like a lot to duplicate the code. – James Wilson Sep 12 '13 at 16:03
  • @adeneo nevermind I fixed it. I just threw my click events inside a function, call the function on initial load, then call it in my .success call back as well. – James Wilson Sep 12 '13 at 16:06
  • I would strongly advice against doing it that way, you should be using delegated event handlers. Give me a second to post an answer. – adeneo Sep 12 '13 at 16:17

3 Answers3

3

You should be using a delegated event handler, like so :

$('#procedures').on('click', '.btnMoveUp', function () {
    var $this = jQuery(this),
        processID = $this.data('processid'),
        currProcedureID = $this.data('procedureid'),
        currSortOrder = $this.data('sortorder'),
        idx = jQuery('.commentlist li').index($this.closest('li')),
        $prevLi = jQuery('.commentlist li').eq(idx - 1),
        $anchor = $prevLi.find('.btnContainer a'),
        prevProcedureID = $anchor.data('procedureid'),
        prevSortOrder = $anchor.data('sortorder');

    // create object that we can pass to MVC controller
    var objProcedure = {};

    objProcedure = {
        _processID: processID,
        _currProcedureID: currProcedureID,
        _currSortOrder: currSortOrder,
        _switchProcedureID: prevProcedureID,
        _switchSortOrder: prevSortOrder
    }

    updateSort(objProcedure);
});
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • I changed it to this method and it works like a charm. I believe you but could you possibly explain why this method is better than the function method just so I can understand it better? Thanks again. – James Wilson Sep 12 '13 at 16:40
  • 1
    This attaches the event handler once on pageload. Attaching the same event handler on every ajax call could potentially lead to problems, like the event handler somehow being attached twice if all the elements for some reason wasn't replaced etc. – adeneo Sep 12 '13 at 17:05
  • @adeneo please check my question about this at: http://stackoverflow.com/questions/23033242/send-partial-view-model-and-update-partial-view-with-jquery-has-issues – QMaster Apr 12 '14 at 16:41
2

I've had a similar problem and it was because the response was being cached. You can set jQuery ajax attributes for caching to false.

$.ajaxSetup({ cache: false });

BenM
  • 4,218
  • 2
  • 31
  • 58
  • 1
    This didn't fix it sadly, but I do think this will fix another issue I was having with caching. :) – James Wilson Sep 12 '13 at 15:54
  • Ahh, well glad I could help at least a little. – BenM Sep 12 '13 at 15:56
  • this will work, but I believe it will turn off all ajax caching, rather than just caching for this update. You can also turn off caching just for a single command by using $.ajax({url: "myurl", success: myCallback, cache: false});, see http://stackoverflow.com/questions/7750447/difference-between-ajaxcachefalse-and-ajaxsetupcachefalse-in-jqu – tomRedox Jan 07 '15 at 10:03
1

Use the [OutputCache] attribute on your action to help avoid caching.

[OutputCache(Duration = 0)]
Matt Houser
  • 33,983
  • 6
  • 70
  • 88