0

I have a datatable with livescroll in my view, and an ajaxstatus component. With most of the components I avoid firing the ajaxstatus dialog by setting:

<p:ajax event="someEvent" global=false\>

in the ajax event, but I don't find a way to do the same with a datatable since there are 'page' and 'sort' events but not a 'scroll' event. Any ideas how to avoid this situation?

  • Did you check the source... it is open. Did you check the documentation? And iirc you can set a global `global='false'` – Kukeltje Sep 25 '19 at 05:41
  • https://github.com/primefaces/primefaces/issues/65, so the only way is to create a patch... Code is fairly easy to understand – Kukeltje Sep 25 '19 at 08:27
  • I checked the documentation and it seems there is no way to catch that event. I'll try adapting the code. Thanks. – imnotthatrobot Sep 25 '19 at 17:12
  • I'll have a quick look too and maybe give you some hints. Do you need specific info in the event? – Kukeltje Sep 25 '19 at 17:14
  • Or do you just want to disable the 'global' ajax feature? The latter is not to difficult – Kukeltje Sep 25 '19 at 17:22

1 Answers1

0

If you 'just' want achieve a global="false" like behaviour, the easiest thing to do is to override the relevant function in the PrimeFaces Datatable.js function and add a global: false in the options of the ajax call that is made under the hood.

This can be done by including the following javascript

PrimeFaces.widget.DataTable.prototype.loadLiveRows: function() {
    if(this.liveScrollActive||(this.scrollOffset + this.cfg.scrollStep > this.cfg.scrollLimit)) {
        return;
    }

    this.liveScrollActive = true;
    this.scrollOffset += this.cfg.scrollStep;

    //Disable scroll if there is no more data left
    if(this.scrollOffset === this.cfg.scrollLimit) {
        this.shouldLiveScroll = false;
    }

    var $this = this,
    options = {
        source: this.id,
        process: this.id,
        update: this.id,
        global: false,    /* Added this so the global is not triggered */
        formId: this.cfg.formId,
        params: [{name: this.id + '_scrolling', value: true},
                        {name: this.id + '_skipChildren', value: true},
                        {name: this.id + '_scrollOffset', value: this.scrollOffset},
                        {name: this.id + '_encodeFeature', value: true}],
        onsuccess: function(responseXML, status, xhr) {
            PrimeFaces.ajax.Response.handle(responseXML, status, xhr, {
                widget: $this,
                handle: function(content) {
                    //insert new rows
                    this.updateData(content, false);

                    this.liveScrollActive = false;
                }
            });

            return true;
        },
        oncomplete: function(xhr, status, args, data) {
            if(typeof args.totalRecords !== 'undefined') {
                $this.cfg.scrollLimit = args.totalRecords;
            }

            $this.loadingLiveScroll = false;
            $this.allLoadedLiveScroll = ($this.scrollOffset + $this.cfg.scrollStep) >= $this.cfg.scrollLimit;

            // reset index of shift selection on multiple mode
            $this.originRowIndex = null;
        }
    };

    PrimeFaces.ajax.Request.handle(options);
},

There unfortunately is no way to partially overide and reuse most (all) of the existing function. I thought you could override the global in a global way so no ajax call triggers the global status. I can unfortunately not find a reference on how to do that anymore.

You can however override the default behaviour in absence of a global setting by overriding Primefaces.ajax.Request.handle

handle: function(cfg, ext) {
    cfg.ext = ext;

    if (PrimeFaces.settings.earlyPostParamEvaluation) {
        cfg.earlyPostParams = PrimeFaces.ajax.Request.collectEarlyPostParams(cfg);
    }

    if(cfg.async) {
        PrimeFaces.ajax.Request.send(cfg);
    }
    else {
        PrimeFaces.ajax.Queue.offer(cfg);
    }
},

By adding an explicit setting of cfg.global to false when absent

var orgHandle = PrimeFaces.ajax.Request.handle;
Primefaces.ajax.Request.prototype.handle = function(cfg, ext) {
     var global = (cfg.global === false || cfg.global === undefined) ? false : true;
     cfg.global = global;
     orgHandle(cfg, ext);
}

Take your pick.

Kukeltje
  • 12,223
  • 4
  • 24
  • 47
  • Sorry for such a newbie question but how should I incorporate this code? Should it be added to the .xhtml as any other js script? I'm refering to the PrimeFaces.widget.DataTable.prototype.loadLiveRows function ... Thank you so much for your answer! – imnotthatrobot Oct 11 '19 at 18:03
  • Yes, but make sure it comes after all other PrimeFaces scripts. I'll see on on monday if I can find a duplicate Q/A, I'm sure there is... cheers – Kukeltje Oct 12 '19 at 07:48