Action/context menu closes prematurely due to data refresh - any workaround

Hello,

I have added a context menu to a table. This is using Vaadin 6.4.8. I have noticed that when you right click on the mouse to display the menu, that the menu closes on its own after about 2 seconds. This is not how context menus behave in other software. Right click on your web browser right now and notice that the menu will not disappear until you select an item, or you click on another window. Is this by design, or a bug in this version of Vaadin I’m using? More importantly, is there a current or upcoming version of Vaadin that addresses this?

Thanks in advance,
David

OK, I think this is not a Vaadin problem, but a consequence of how our app does refreshing. We have a column in the table that shows the amount of time that a “channel” represented by the row has been running. The time is updated every 2 seconds using a background thread. Is there a way to update row data like this without creating a custom component, and without the update closing any context menus that are open?

Thanks in advance,
David

I am experiencing a similar issue. I am using the Refresher add on to refresh the UI on a regular basis and my context menus disappear when the refresh quicks in. Can we get some pointers from the Vaadin team on how to maybe fix this?
Best regards,
Guillaume Belrose.

I had to implement a custom Table implementation to do this as, by default, whenever the table is repainted the context menu disappears. This is highly problematic for push-based applications (like mine). Unfortunately, the client widget for Table is next to impossible to do any sub-classing so you’d have to clone it and modify it. The basic idea revolves on ensuring you have a unique item id that can be easily passed back and forth from client to server and vice versa. For me, we used the hibernate entity ids (long values). Create a subclass of Table and override paintRowAttributes method like so:


    @Override
    protected void paintRowAttributes(PaintTarget target, Object itemId) throws PaintException {
        target.addAttribute("iid", itemId.toString()); // Links context menu with item id
    }

The create clone of VScrollTable. The changes need to be made to the VScrollTableRow. In constructor, check UIDL for “iid” param and save in instance variable:


if (uidl.hasAttribute("iid"))
    this.rowItemId = uidl.getStringAttribute("iid");
VConsole.log("row key: " + this.rowKey + "; item id: " + this.rowItemId);

then use rowItemId when showing context menu for row instead of row key:


            public void showContextMenu(Event event) {
                if (enabled && actionKeys != null) {
                    // Show context menu if there are registered action handlers
                    int left = Util.getTouchOrMouseClientX(event);
                    int top = Util.getTouchOrMouseClientY(event);
                    top += Window.getScrollTop();
                    left += Window.getScrollLeft();
                    contextMenu = new ContextMenuDetails(this.rowItemId, left, top);
                    client.getContextMenu().showAt(this, left, top);
                }
            }

finally, change rowKey to rowItemId in the table’s updateFromUIDL method (around line 1015 in Vaadin 6.8.6) to re-open context menu on an update:


      if (enabled && savedContextMenu != null) {
            for (Widget w : scrollBody.renderedRows) {
                VScrollTableBody.VScrollTableRow row = (VScrollTableBody.VScrollTableRow) w;
                if (row.isVisible()
                        && savedContextMenu.rowKey.equals(row.rowItemId)) {
                    contextMenu = savedContextMenu;
                    client.getContextMenu().showAt(row, savedContextMenu.left,
                            savedContextMenu.top);
                }
            }
        }