Primefaces: Tree: add a callback for filtering

Created on 30 Apr 2018  路  4Comments  路  Source: primefaces/primefaces

It would be useful to have a way to register a javascript callback when filtering is applied to the tree.
My use case is that I want to highlight the search terms in the resulting tree nodes, but I can imagine other uses.

1) Environment

  • PrimeFaces version: 6.2.3
  • Does it work on the newest released PrimeFaces version? No
  • Does it work on the newest sources in GitHub? Not tried
  • Application server + version: Tomcat 8.5.20
  • Affected browsers: Firefox, Chrome, Edge

2) Expected behavior

Have a onfilter attribute on <p:tree> component to register a javascript callback.

<p:tree value="#{treeBean.root}" var="node" filterBy="#{node}" onfilter="doMyStuffAfterFiltering()">
    <p:treeNode>
        <h:outputText value="#{node}"/>
    </p:treeNode>
</p:tree>

3) Actual behavior

The only way I found to workaround the problem is to wrap the tree filter() function with a callback.

function addTreeFilterCallback(tree, callback) {
    var initialFilterFunction = tree.filter;
    tree.filter = function () {
        initialFilterFunction.call(tree);
        callback();
    }
}

But, of course, since the filter() is asynchronous, my callback is called before the filtering updates the DOM.
Therefore I register a MutationObserver in the callback to capture changes made to the DOM after the filtering.

var searchInput = '';
var observer = new MutationObserver(function (mutations) {
    doMyStuffAfterFiltering(searchInput);
    this.disconnect();
});

var config = {childList: true, subtree: true};
observer.observe(tree.jq[0], config);

this.addTreeFilterCallback(tree, function () {
    searchInput = tree.jq.find('.ui-tree-filter').val();
    observer.observe(tree.jq[0], config);
});

All this would be much simpler with a built-in callback that could be called from the onsuccess() function inside filter().

    filter: function() {
        var $this = this,
        options = {
            source: this.id,
            update: this.id,
            process: this.id,
            global: false,
            formId: this.cfg.formId,
            params: [{name: this.id + '_filtering', value: true},
                     {name: this.id + '_encodeFeature', value: true}],
            onsuccess: function(responseXML, status, xhr) {
                PrimeFaces.ajax.Response.handle(responseXML, status, xhr, {
                    widget: $this,
                    handle: function(content) {
                        $this.container.html(content);
                    }
                });
               // callback here

                return true;
            }
        };

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

It would be even easier if the callback would pass the search term as an argument.

documentation new feature

Most helpful comment

You can use now:

All 4 comments

Why not just use
p:ajax event="filter" onsucess...?

This could be a solution, even if it creates one extra round-trip, but it gives me an error:

Event:filter is not supported.

And by looking at the doc (6.2), not surprisingly, filter event is not mentioned (only expand, colapse, select and unselect).

So we should add the filter event as we already have a ajax request for the filtering.

You can use now:

Was this page helpful?
0 / 5 - 0 ratings