12 Eylül 2013 Perşembe

Primefaces Datatable Contextmenu Disappear Problem Fix

Updatable context menu is a big problem if you are using tree or datatable component of Primefaces. For example in my case, I have a datatable that has row which has different boolean flags. Depending of that flags, I have to change my context menu items. Basically, I have to render different context menus for each row in my datatable. First I tried to update context menu in element but there was a problem which I was finally able to solve...

ContextMenu component has two phases. One is generate or update phase and the other is show phase. If you try to update your context menu on right click, show phase comes first and then it updates itself. After this process, you will see that you context menu appears and disappears. While I was searching for a workaround, I found a post which helped me a lot in Primefaces forum. A guy found a solution which is overriding show function of context menu and then calling this method right after update process is done. This is the best solution I think. That guy applied this workaround for tree component. Below, you can find this approach that is applied to datatable.

<script type="text/javascript">
//patch to fix a problem that the context menu disappears after update
//delay the show to occure after the update 
var siteFunctions = {
    patchContextMenuShow: function() {
        var protShow = PrimeFaces.widget.ContextMenu.prototype.show;
        siteFunctions.patchContextMenuShow.lastEvent = null;
        PrimeFaces.widget.ContextMenu.prototype.show = function(e) {
            var ret;
            if (e) {
//saving last event
                siteFunctions.patchContextMenuShow.lastEvent = e;
                siteFunctions.patchContextMenuShow.lastEventArg = arguments;
                siteFunctions.patchContextMenuShow.lastEventContext = this;
            } else if (siteFunctions.patchContextMenuShow.lastEvent) {
//executing last event
                ret = protShow.apply(siteFunctions.patchContextMenuShow.lastEventContext, siteFunctions.patchContextMenuShow.lastEventArg);
//clearing last event
                siteFunctions.patchContextMenuShow.lastEvent = null;
            }
            return ret;
        };
    }
};

$(document).ready(function() {
    try {
        siteFunctions.patchContextMenuShow();
    } catch (e) {
        console.error(e);
    }
});
</script>

<p:contextmenu beforeshow="return true;" 
               for="dataTable" 
               id="contextMenuID" 
               widgetvar="tableContextMenuWV">
   <p:menuitem value="Menu 1" />
   <p:menuitem value="Menu 2" />
</p:contextmenu>
                
<p:datatable id="dataTable" widgetvar="dataTableW">
   <p:ajax event="contextMenu" 
           oncomplete="tableContextMenuWV.show();" 
           update=":formList:contextMenuID" />
</p:datatable>
( primefaces, jsf, datatable, row, context menu, update, show, disappear )
Kaynak : http://forum.primefaces.org/viewtopic.php?f=3&t=26813