DataTables / DataTablesSrc

DataTables source repository
https://datatables.net
MIT License
587 stars 422 forks source link

Fix for "resetPaging" parameter ignored on Ajax reload #238

Closed sodium24 closed 1 year ago

sodium24 commented 1 year ago

As detailed in several previous discussion forum posts (https://datatables.net/forums/discussion/36000/how-to-store-scroller-position-when-use-ajax-reload for example), there is a known issue that DataTables will always reset the scroll position to the top of the table on an ajax.reload(), even if the resetPaging parameter is false (e.g. ajax.reload(null, false)).

The suggested workarounds in the various forum posts do not smoothly solve the problem when using the Scroller extension.

I put together a demo illustrating the problem here. The table will reload once per second, resetting the scroll position.

I was able to figure out the root cause and found a solution to the problem, as demonstrated here.

The problem is in the following code:

core.draw.js function _fnReDraw https://github.com/DataTables/DataTablesSrc/blob/5ea3870910bd46b2afa4dad7f985caaabc3c58d4/js/core/core.draw.js#L479-L483

core.draw.js function _fnDraw https://github.com/DataTables/DataTablesSrc/blob/5ea3870910bd46b2afa4dad7f985caaabc3c58d4/js/core/core.draw.js#L363

core.ajax.js function _fnAjaxUpdate https://github.com/DataTables/DataTablesSrc/blob/5ea3870910bd46b2afa4dad7f985caaabc3c58d4/js/core/core.ajax.js#L156-L162

core.ajax.js function _fnAjaxUpdateDraw https://github.com/DataTables/DataTablesSrc/blob/5ea3870910bd46b2afa4dad7f985caaabc3c58d4/js/core/core.ajax.js#L320

The problem with this code is that _fnDraw is called twice: the first time synchronously before the Ajax reload, and the second time asynchronously after the Ajax reloads. The second time it is called, settings._drawHold will always be false regardless of the resetPaging function parameter.

A working fix for this issue is to keep track of the _drawHold state in _fnAjaxUpdate and set it appropriately in the async callback function:

    // Keep track of drawHold state to handle scrolling after the Ajax call
    var drawHold = settings._drawHold;

    _fnBuildAjax(
        settings,
        _fnAjaxParameters( settings ),
        function(json) {
            settings._drawHold = drawHold;
            _fnAjaxUpdateDraw( settings, json );
            settings._drawHold = false;
        }
    );

I'd be happy to open a PR for this fix.