0

I've made a simple scroll content loading feature based on primefaces datatable:

PF('tableWidget').jq.bind("scrollstop", function() { 
    var t = PF('tableWidget');
    if(t.jq.scrollTop() + t.jq.height() >= t.jq.children().height()) {
        var rows = t.jq.find('tr');                       //save current rows
        $.ajaxSetup({async: false});                      //ajax set sync
        t.paginator.setPage(t.paginator.cfg.page + 1);    //framework pagination function with an ajax call inside (and other stuff) to get new rows
        rows.prependTo(t.jq.find('tbody'));               //AFTER pagination, add old rows
        $.ajaxSetup({async: true});                       //ajax set async again
    } 
});

Explanation: When a user scrolls down to the bottom of the dataTable, I just use the pagination, but save the old rows before. After finishing the pagination, I add the rows again. This leaves to a super cool scroll based loading, where only new data needs to be loaded from the server, and not the old content again.

But as I read in other questions, using synchronized ajax calls is bad practice.

It's not easy to override the "t.paginator.setPage(x)" function, because in this function there is anywhere an ajax call.

Is there a way, to wrap that whole function, and add some success callback to it, without digging down to the real basic ajax call?

Thanks a lot!

kaiser
  • 940
  • 1
  • 10
  • 25

2 Answers2

0

You can have setPage return the $.ajax promise and do what you need in a promise callback.

t.paginator.setPage = function(pageNum){
  // return the promise
  return $.ajax(....);
};

Then when you call it do:

t.paginator.setPage(t.paginator.cfg.page + 1).then(function(){
   rows.prependTo(t.jq.find('tbody'));  
}); 
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Thanks for this answer, but here you are overriding the setPage function. It is already implemented in a framework with a lot of different function calls, one of that calls is the ajax call. Is there no way to wrap the setPage function and get the ajax call event? Let's say with some binding, or anything else. – kaiser Feb 16 '17 at 15:44
  • No, not really...that is the nature of asynchronous coding. You could try using a global method like `$( document ).ajaxSuccess()` and check the url used or some other setting that would indicate it is pager related – charlietfl Feb 16 '17 at 16:22
  • thanks, i already tried to bind ajaxSuccess to the dataTable (parent of paginator), but the event isn't fired. – kaiser Feb 16 '17 at 16:33
  • Need to say thanks again, your input helped to find i perfect solution!!! I'll post it as answer – kaiser Feb 16 '17 at 17:02
0

Here is my solution: Because i needed to get access to paginator onsuccess or oncomplete method i now use the given ajax listener of the primefaces dataTable. The whole code for a scroll based content load system looks like this:

<p:dataTable id="table" value="#{items}" var="item" paginator="true" widgetVar="tableWidget">
    <p:ajax event="page" onstart="storeRows()" oncomplete="restoreRows()"/>
    ...
</p:dataTable>

<h:outputScript>
    <!-- variables -->
    var rows;

    <!-- scroll bottom to load more -->
    PF('tableWidget').jq.bind("scrollstop", function() { 
        var t = PF('tableWidget');
        if(t.jq.scrollTop() + t.jq.height() >= t.jq.children().height()) {
            t.paginator.setPage(t.paginator.cfg.page + 1);
        } 
    });

    <!-- store and restore rows -->
    function storeRows() {
        var t = PF('tableWidget');
        rows = t.jq.find('tr'); 
    }

    function restoreRows() {
        var t = PF('tableWidget');
        rows.prependTo(t.jq.find('tbody'));
    }
</h:outputScript>
kaiser
  • 940
  • 1
  • 10
  • 25