flow-components
flow-components copied to clipboard
Provide columnId for grid context menu dynamic content handler
Current API with GridContextMenu is like follows
contextMenu.setDynamicContentHandler(item -> {
...
});
This makes possible to populate the GridContextMenu based on item clicked.
However sometimes there is need dynamically populate the menu based on the specific column clicked as well.
Currently this is not possible since only method to get column info is in GridContextMenuOpenedEvent, which fired after DynamicContentHandler is processed.
contextMenu.addGridContextMenuOpenedListener(event -> {
columnId event.getColumnId();
...
});
Thus there is a need for API like using BiFunction in the handler
contextMenu.setDynamicContentHandler((item,columnId) -> {
...
});
Note, this was possible in Vaadin 8.
Possible workaround 1: Use DomEvent listener to observe contextmenu
String expression = "function(){const col=element.getEventContext(event).column;return col ? col.id : '';}()";
getElement().addEventListener("contextmenu", event -> {
String colId = event .getEventData().getString(expression);
Optional<Column<Bean>> column = getColumns().stream().filter(col -> colId.equals(col.getId().get())).findFirst();
System.out.println("setting domevent column id: " + column.get().getId().get());
domEventColumn = column.get();
}).addEventData(expression);
GridContextMenu<Bean> contextMenu = addContextMenu();
contextMenu.setDynamicContentHandler(wab -> {
System.out.println("dynamicContentHandler " + domEventColumn.getId().get());
return true;
});
Possible workaround 2: Use alternative approach, for example Popup add-on in component renderer
personGrid.addComponentColumn(item -> {
HorizontalLayout layout = new HorizontalLayout();
Span text = new Span();
text.setText(item.getName());
layout.add(text);
String id = "cell"+Math.abs(rand.nextInt());
text.setId(id);
Popup popup = new Popup();
layout.add(popup);
popup.setFor(id);
VerticalLayout div = new VerticalLayout();
Button button1 = new Button("Click "+item.getName());
Button button2 = new Button("Delete");
div.add(button1,button2);
popup.add(div);
layout.addClickListener(event -> {
popup.setOpened(true);
});
return layout;
}).setKey("name");
In our application, this feature was required and we therefor created a custom grid-connector which adds this functionality. The duplicate issue #424 has a referenced PR (closed) which shows our current solution.
Wouldn't it be preferable to get the column-key or even the column-instance instead of the column-id? Like mentioned in https://stackoverflow.com/questions/77117774/get-vaadin-grid-column-by-its-id column-id seems more like a internal identifier and an existing getter of Grid isn't accessible: Grid#getColumnByInternalId()
Regardless what id/key we could get, the nicest way for me would be to get the column-instance directly like so (because I stored some additional data in the column):
contextMenu.setDynamicContentHandler((item,column) -> {
ColumnData data = ComponentUtil.getData(column, ColumnData.class);
...
});