Search code examples
primefacesjsf-2treecontextmenu

Primefaces tree dynamic contextmenu


I need a dynamic context menu for a tree (different on each node based on some permissions, so I cannot use a different menu for each node's type).

I have implemented it using a backing bean model and I update it on every selection's change. Everything works fine, except that if the user right click an unselected node the following happens:

  • context menu (of previously selected node) is showed
  • context menu is updated (triggered by select event) and than hidden again
  • right click again shows the updated context menu

I have found I workaround for treetable https://dnhome.wordpress.com/2013/10/07 ... e-of-tree/

but it doesn't work for a tree.

Any hint is welcome


PF 6.1.2, WF 10.0.0


Solution

  • Neo's answer is correct but a bit too verbose and overrides all context menus on the page instead of a specific one. This is a cleaner version with explanation.

    <p:tree id="tree">
        <!-- when showing the menu, update it first and then call show a second time -->
        <p:ajax event="contextMenu" update="@parent-ctx_menu"
            oncomplete="PF('ctxMenuVar').show()" />
    </p:tree>
    
    <p:contextMenu id="ctx_menu" for="tree" widgetVar="ctxMenuVar" />
    
    <script>
        $(function() {
            var ctxMenuWidget = PF('ctxMenuVar');
            (function(orig) {
                ctxMenuWidget.show = function(e) {
                    if (e) {
                        // this is the first show call by PrimeFaces - let's remember the
                        // argument event, and wait for the update
                        this.lastShowEvent = e;
                        e.preventDefault();
                    } else {
                        // this is our second show call from oncomplete - the menu is updated,
                        // time to actually show it
                        checkState(this.lastShowEvent);
                        orig.call(this, this.lastShowEvent);
                    }
                };
            })(ctxMenuWidget.show);
        });
    </script>
    

    This works at least for PrimeFaces 6.1, but probably for later versions as well.