From f387219333e20933b4e44da69525d9686344674f Mon Sep 17 00:00:00 2001
From: "totally-not-ai[bot]"
<290682512+totally-not-ai[bot]@users.noreply.github.com>
Date: Sat, 3 Oct 2026 06:18:15 +0000
Subject: [PATCH 1/7] test: verify grid context menu target column is set
before dynamic content handler
Co-Authored-By: Claude Opus 5.5
---
.../grid/contextmenu/GridContextMenuTest.java | 37 +++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
index af4894fe9b2..2bb67870fd5 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
@@ -16,6 +16,7 @@
package com.vaadin.flow.component.grid.contextmenu;
import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -25,13 +26,17 @@
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.contextmenu.ContextMenu;
+import com.vaadin.flow.component.contextmenu.ContextMenuBase;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.contextmenu.MenuManager;
import com.vaadin.flow.component.contextmenu.SubMenu;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.contextmenu.GridContextMenu.GridContextMenuItemClickEvent;
import com.vaadin.flow.component.html.NativeButton;
+import com.vaadin.flow.dom.DomEvent;
import com.vaadin.flow.function.SerializableRunnable;
+import com.vaadin.flow.internal.JacksonUtils;
+import com.vaadin.flow.internal.nodefeature.ElementListenerMap;
class GridContextMenuTest {
@@ -136,4 +141,36 @@ void multipleContextMenus_clearTargetOfOne_getContextMenusKeepsOthers() {
Assertions.assertEquals(List.of(first, third), grid.getContextMenus());
}
+
+ @Test
+ void dynamicContentHandler_targetColumnIdIsUpdatedBeforeHandlerRuns() {
+ Grid grid = new Grid<>();
+ grid.addColumn(item -> item).setId("first");
+ grid.addColumn(item -> item).setId("second");
+ GridContextMenu contextMenu = grid.addContextMenu();
+
+ AtomicReference columnIdInHandler = new AtomicReference<>();
+ contextMenu.setDynamicContentHandler(item -> {
+ columnIdInHandler.set(grid.getElement()
+ .getProperty("_contextMenuTargetColumnId"));
+ return false;
+ });
+
+ fireBeforeOpenEvent(grid, "second");
+ Assertions.assertEquals("second", columnIdInHandler.get());
+
+ fireBeforeOpenEvent(grid, "first");
+ Assertions.assertEquals("first", columnIdInHandler.get());
+ }
+
+ private static void fireBeforeOpenEvent(Grid> grid, String columnId) {
+ var detail = JacksonUtils.createObjectNode();
+ detail.put("key", "");
+ detail.put("columnId", columnId);
+ var eventData = JacksonUtils.createObjectNode();
+ eventData.set(ContextMenuBase.EVENT_DETAIL, detail);
+ grid.getElement().getNode().getFeature(ElementListenerMap.class)
+ .fireEvent(new DomEvent(grid.getElement(),
+ "vaadin-context-menu-before-open", eventData));
+ }
}
From 25ffef6392fd813dd3fe07769c3a72eb4828001d Mon Sep 17 00:00:00 2001
From: "totally-not-ai[bot]"
<290682512+totally-not-ai[bot]@users.noreply.github.com>
Date: Sat, 3 Oct 2026 06:24:05 +0000
Subject: [PATCH 2/7] feat: pass clicked column to grid context menu dynamic
content handler
Add a GridContextMenu#setDynamicContentHandler overload whose callback
receives both the clicked item and the clicked column. Also update the
context menu target item and column before running the dynamic content
handler, so that they are no longer one click behind.
Co-Authored-By: Claude Opus 5.5
---
.../DynamicContextMenuGridPage.java | 26 +++++++
.../contextmenu/DynamicContextMenuGridIT.java | 21 ++++-
.../test/grid-connector-context-menu.test.ts | 5 +-
.../grid/contextmenu/GridContextMenu.java | 76 ++++++++++++++++++-
.../frontend/vaadin-grid/gridConnector.ts | 3 +-
.../vaadin-grid/vaadin-grid-types.d.ts | 6 +-
.../grid/contextmenu/GridContextMenuTest.java | 62 ++++++++++++++-
7 files changed, 192 insertions(+), 7 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java
index b72d960a94f..b162d8c3ff5 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java
@@ -27,6 +27,7 @@ public class DynamicContextMenuGridPage extends Div {
public DynamicContextMenuGridPage() {
gridWithDynamicContextMenu();
+ gridWithColumnDynamicContextMenu();
}
private void gridWithDynamicContextMenu() {
@@ -53,4 +54,29 @@ private void gridWithDynamicContextMenu() {
grid.setId("grid-with-dynamic-context-menu");
add(grid);
}
+
+ private void gridWithColumnDynamicContextMenu() {
+ final Grid grid = new Grid<>();
+ Grid.Column nameColumn = grid.addColumn(Person::getFirstName)
+ .setHeader("Name");
+ grid.addColumn(Person::getAge).setHeader("Age");
+
+ grid.setItems(IntStream.range(0, 50)
+ .mapToObj(i -> new Person("Person " + i, i)).toList());
+
+ GridContextMenu contextMenu = grid.addContextMenu();
+
+ contextMenu.setDynamicContentHandler((person, column) -> {
+ contextMenu.removeAll();
+ if (person != null) {
+ contextMenu.addItem(
+ column == nameColumn ? "Call " + person.getFirstName()
+ : "Age " + person.getAge());
+ }
+ return person != null;
+ });
+
+ grid.setId("grid-with-column-dynamic-context-menu");
+ add(grid);
+ }
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java
index 0993f311798..c07b88820e2 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java
@@ -36,7 +36,7 @@ public class DynamicContextMenuGridIT extends AbstractComponentIT {
@Before
public void init() {
open();
- grid = $(GridElement.class).first();
+ grid = $(GridElement.class).id("grid-with-dynamic-context-menu");
verifyClosed();
}
@@ -76,6 +76,25 @@ public void shouldOpenContextMenuWhenClickingOnTheEdgeOfCell() {
getContextMenu().getDomProperty("innerText"));
}
+ @Test
+ public void columnDynamicContentHandler_menuContentDependsOnClickedColumn() {
+ GridElement columnGrid = $(GridElement.class)
+ .id("grid-with-column-dynamic-context-menu");
+
+ columnGrid.getCell(5, 1).contextClick();
+ verifyOpened();
+ Assert.assertEquals("Age 5",
+ getContextMenu().getDomProperty("innerText"));
+
+ $("body").first().click();
+ verifyClosed();
+
+ columnGrid.getCell(5, 0).contextClick();
+ verifyOpened();
+ Assert.assertEquals("Call Person 5",
+ getContextMenu().getDomProperty("innerText"));
+ }
+
private TestBenchElement getContextMenu() {
return $("vaadin-context-menu").first();
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/test/grid-connector-context-menu.test.ts b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/test/grid-connector-context-menu.test.ts
index 34bcdfebb3a..18202172fbe 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/test/grid-connector-context-menu.test.ts
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/test/grid-connector-context-menu.test.ts
@@ -23,6 +23,7 @@ describe('grid connector - context menu', () => {
column = grid.querySelector('vaadin-grid-column')!;
column.id = 'name-column';
+ column._flowId = 'col0';
setRootItems(grid.$connector, [
{ key: '0', name: 'foo' },
@@ -41,14 +42,14 @@ describe('grid connector - context menu', () => {
});
it('should return item key and column id in before-open detail', () => {
- let detail: { key: string, columnId: string };
+ let detail: { key: string; columnId: string; internalColumnId: string };
// The detail is resolved while the source event is still being dispatched
grid.addEventListener('contextmenu', (e) => {
detail = grid.getContextMenuBeforeOpenDetail(new CustomEvent('contextmenu', { detail: { sourceEvent: e } }));
});
getBodyCellContent(grid, 0, 1)!.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, composed: true }));
- expect(detail!).to.deep.equal({ key: '0', columnId: 'name-column' });
+ expect(detail!).to.deep.equal({ key: '0', columnId: 'name-column', internalColumnId: 'col0' });
});
it('should prevent context menu on selection column left click', () => {
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
index 00acfa044e4..2eeeb60fd2c 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
@@ -25,6 +25,7 @@
import com.vaadin.flow.component.contextmenu.MenuManager;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.function.SerializableBiFunction;
+import com.vaadin.flow.function.SerializableBiPredicate;
import com.vaadin.flow.function.SerializablePredicate;
import com.vaadin.flow.function.SerializableRunnable;
import com.vaadin.flow.shared.Registration;
@@ -44,6 +45,7 @@ public class GridContextMenu extends
implements HasGridMenuItems {
private SerializablePredicate dynamicContentHandler;
+ private SerializableBiPredicate> columnDynamicContentHandler;
/**
* Event that is fired when a {@link GridMenuItem} is clicked inside a
@@ -247,7 +249,9 @@ public Registration addGridContextMenuOpenedListener(
*
*
* @return the callback function that is executed before opening the context
- * menu, or {@code null} if not specified.
+ * menu, or {@code null} if not specified or if a handler that also
+ * receives the column was set with
+ * {@link #setDynamicContentHandler(SerializableBiPredicate)}.
* @since 4.1
*/
public SerializablePredicate getDynamicContentHandler() {
@@ -267,6 +271,10 @@ public SerializablePredicate getDynamicContentHandler() {
* The boolean return value of this callback specifies if the context menu
* will be opened.
*
+ *
+ * Replaces any handler set with
+ * {@link #setDynamicContentHandler(SerializableBiPredicate)}.
+ *
*
* @param dynamicContentHandler
* the callback function that will be executed before opening the
@@ -276,6 +284,50 @@ public SerializablePredicate getDynamicContentHandler() {
public void setDynamicContentHandler(
SerializablePredicate dynamicContentHandler) {
this.dynamicContentHandler = dynamicContentHandler;
+ this.columnDynamicContentHandler = null;
+ }
+
+ /**
+ * Sets a callback that is executed before the context menu is opened, and
+ * that receives both the clicked item and the clicked column.
+ *
+ *
+ * Use this to build context menus whose contents depend on the column that
+ * was clicked, for example:
+ *
+ *
+ *
+ * contextMenu.setDynamicContentHandler((person, column) -> {
+ * contextMenu.removeAll();
+ * if (column == nameColumn) {
+ * contextMenu.addItem("Call", e -> call(person));
+ * } else if (column == addressColumn) {
+ * contextMenu.addItem("Show on map", e -> showOnMap(person));
+ * }
+ * return true;
+ * });
+ *
+ *
+ *
+ * The item is {@code null} if the context-click didn't target an item (eg.
+ * a header). The column is {@code null} if the context-click didn't target
+ * an application column (eg. the selection column). The boolean return
+ * value of this callback specifies if the context menu will be opened.
+ *
+ *
+ * Replaces any handler set with
+ * {@link #setDynamicContentHandler(SerializablePredicate)}.
+ *
+ *
+ * @param dynamicContentHandler
+ * the callback function that will be executed before opening the
+ * context menu, or {@code null} to remove it
+ * @since 25.4
+ */
+ public void setDynamicContentHandler(
+ SerializableBiPredicate> dynamicContentHandler) {
+ this.columnDynamicContentHandler = dynamicContentHandler;
+ this.dynamicContentHandler = null;
}
/**
@@ -287,6 +339,20 @@ public void setDynamicContentHandler(
protected boolean onBeforeOpenMenu(ObjectNode eventDetail) {
Grid grid = (Grid) getTarget();
String key = eventDetail.get("key").asString();
+ String columnId = eventDetail.get("columnId").asString();
+
+ // The grid connector also reports the target with a separate server
+ // call, which is processed after this event. Update the target here so
+ // that it is up to date in the dynamic content handlers.
+ grid.getElement().setProperty("_contextMenuTargetItemKey", key);
+ grid.getElement().setProperty("_contextMenuTargetColumnId", columnId);
+
+ if (columnDynamicContentHandler != null) {
+ final T item = grid.getDataCommunicator().getKeyMapper().get(key);
+ final Grid.Column column = getColumnByInternalId(grid,
+ eventDetail.get("internalColumnId").asString());
+ return columnDynamicContentHandler.test(item, column);
+ }
if (getDynamicContentHandler() != null) {
final T item = grid.getDataCommunicator().getKeyMapper().get(key);
@@ -295,4 +361,12 @@ protected boolean onBeforeOpenMenu(ObjectNode eventDetail) {
return super.onBeforeOpenMenu(eventDetail);
}
+
+ private static Grid.Column getColumnByInternalId(Grid grid,
+ String internalId) {
+ return grid.getColumns().stream()
+ .filter(column -> internalId
+ .equals(column.getElement().getProperty("_flowId")))
+ .findFirst().orElse(null);
+ }
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/gridConnector.ts b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/gridConnector.ts
index c647c2d0b30..08c57989726 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/gridConnector.ts
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/gridConnector.ts
@@ -512,7 +512,8 @@ export class GridConnector {
const eventContext = grid.getEventContext(sourceEvent);
const key = eventContext.item?.key || '';
const columnId = eventContext.column?.id || '';
- return { key, columnId };
+ const internalColumnId = eventContext.column?._flowId ?? '';
+ return { key, columnId, internalColumnId };
};
grid.preventContextMenu = (event) => {
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/vaadin-grid-types.d.ts b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/vaadin-grid-types.d.ts
index 429a2e93039..971842023b8 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/vaadin-grid-types.d.ts
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/resources/META-INF/frontend/vaadin-grid/vaadin-grid-types.d.ts
@@ -93,7 +93,11 @@ export interface FlowGridInternals {
_isDetailsOpened(item: Item | undefined): boolean;
isItemSelectable(item: Item | null | undefined): boolean;
_mapSorters(): GridSorterDefinition[];
- getContextMenuBeforeOpenDetail(event: CustomEvent<{ sourceEvent?: Event }>): { key: string; columnId: string };
+ getContextMenuBeforeOpenDetail(event: CustomEvent<{ sourceEvent?: Event }>): {
+ key: string;
+ columnId: string;
+ internalColumnId: string;
+ };
preventContextMenu(event: MouseEvent): boolean;
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
index 2bb67870fd5..be5a5d1d87f 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
@@ -163,10 +163,70 @@ void dynamicContentHandler_targetColumnIdIsUpdatedBeforeHandlerRuns() {
Assertions.assertEquals("first", columnIdInHandler.get());
}
+ @Test
+ void columnDynamicContentHandler_receivesClickedItemAndColumn() {
+ Grid grid = new Grid<>();
+ grid.setItems("foo", "bar");
+ Grid.Column first = grid.addColumn(item -> item);
+ Grid.Column second = grid.addColumn(item -> item);
+ GridContextMenu contextMenu = grid.addContextMenu();
+
+ AtomicReference itemInHandler = new AtomicReference<>();
+ AtomicReference> columnInHandler = new AtomicReference<>();
+ contextMenu.setDynamicContentHandler((item, column) -> {
+ itemInHandler.set(item);
+ columnInHandler.set(column);
+ return false;
+ });
+
+ String barKey = grid.getDataCommunicator().getKeyMapper().key("bar");
+ fireBeforeOpenEvent(grid, barKey, "", getInternalId(second));
+ Assertions.assertEquals("bar", itemInHandler.get());
+ Assertions.assertSame(second, columnInHandler.get());
+
+ fireBeforeOpenEvent(grid, "", "", getInternalId(first));
+ Assertions.assertNull(itemInHandler.get());
+ Assertions.assertSame(first, columnInHandler.get());
+
+ // Not an application column, e.g. the selection column
+ fireBeforeOpenEvent(grid, barKey, "", "");
+ Assertions.assertEquals("bar", itemInHandler.get());
+ Assertions.assertNull(columnInHandler.get());
+ }
+
+ @Test
+ void setDynamicContentHandler_replacesHandlerOfOtherType() {
+ GridContextMenu contextMenu = new Grid()
+ .addContextMenu();
+
+ contextMenu.setDynamicContentHandler(item -> true);
+ contextMenu.setDynamicContentHandler((item, column) -> true);
+ Assertions.assertNull(contextMenu.getDynamicContentHandler());
+
+ AtomicReference called = new AtomicReference<>(false);
+ contextMenu.setDynamicContentHandler((item, column) -> {
+ called.set(true);
+ return false;
+ });
+ contextMenu.setDynamicContentHandler(item -> false);
+ fireBeforeOpenEvent((Grid>) contextMenu.getTarget(), "", "", "");
+ Assertions.assertFalse(called.get());
+ }
+
+ private static String getInternalId(Grid.Column> column) {
+ return column.getElement().getProperty("_flowId");
+ }
+
private static void fireBeforeOpenEvent(Grid> grid, String columnId) {
+ fireBeforeOpenEvent(grid, "", columnId, "");
+ }
+
+ private static void fireBeforeOpenEvent(Grid> grid, String key,
+ String columnId, String internalColumnId) {
var detail = JacksonUtils.createObjectNode();
- detail.put("key", "");
+ detail.put("key", key);
detail.put("columnId", columnId);
+ detail.put("internalColumnId", internalColumnId);
var eventData = JacksonUtils.createObjectNode();
eventData.set(ContextMenuBase.EVENT_DETAIL, detail);
grid.getElement().getNode().getFeature(ElementListenerMap.class)
From 9bc39db3ab4f8076ba379afa0ce28fb57a42c911 Mon Sep 17 00:00:00 2001
From: "totally-not-ai[bot]"
<290682512+totally-not-ai[bot]@users.noreply.github.com>
Date: Sun, 4 Oct 2026 05:43:38 +0000
Subject: [PATCH 3/7] refactor: deprecate item-only grid context menu dynamic
content handler
Co-Authored-By: Claude Opus 5.5
---
.../component/grid/contextmenu/GridContextMenu.java | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
index 2eeeb60fd2c..6cca1ca6ceb 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
@@ -253,7 +253,12 @@ public Registration addGridContextMenuOpenedListener(
* receives the column was set with
* {@link #setDynamicContentHandler(SerializableBiPredicate)}.
* @since 4.1
+ * @deprecated Use
+ * {@link #setDynamicContentHandler(SerializableBiPredicate)} to
+ * set a handler that also receives the clicked column. There is
+ * no replacement for getting the handler.
*/
+ @Deprecated(since = "25.4", forRemoval = true)
public SerializablePredicate getDynamicContentHandler() {
return dynamicContentHandler;
}
@@ -280,7 +285,11 @@ public SerializablePredicate getDynamicContentHandler() {
* the callback function that will be executed before opening the
* context menu.
* @since 4.1
+ * @deprecated Use
+ * {@link #setDynamicContentHandler(SerializableBiPredicate)}
+ * instead, which also receives the clicked column.
*/
+ @Deprecated(since = "25.4", forRemoval = true)
public void setDynamicContentHandler(
SerializablePredicate dynamicContentHandler) {
this.dynamicContentHandler = dynamicContentHandler;
@@ -354,9 +363,9 @@ protected boolean onBeforeOpenMenu(ObjectNode eventDetail) {
return columnDynamicContentHandler.test(item, column);
}
- if (getDynamicContentHandler() != null) {
+ if (dynamicContentHandler != null) {
final T item = grid.getDataCommunicator().getKeyMapper().get(key);
- return getDynamicContentHandler().test(item);
+ return dynamicContentHandler.test(item);
}
return super.onBeforeOpenMenu(eventDetail);
From bc4a5446d586856d48ed7894ced4b37f31cb05d0 Mon Sep 17 00:00:00 2001
From: "totally-not-ai[bot]"
<290682512+totally-not-ai[bot]@users.noreply.github.com>
Date: Sun, 4 Oct 2026 05:44:32 +0000
Subject: [PATCH 4/7] fix: keep using dynamic content handler getter in
onBeforeOpenMenu
Co-Authored-By: Claude Opus 5.5
---
.../flow/component/grid/contextmenu/GridContextMenu.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
index 6cca1ca6ceb..ea6c58efa07 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
@@ -344,6 +344,7 @@ public void setDynamicContentHandler(
*
* @since 25.0
*/
+ @SuppressWarnings("removal")
@Override
protected boolean onBeforeOpenMenu(ObjectNode eventDetail) {
Grid grid = (Grid) getTarget();
@@ -363,9 +364,9 @@ protected boolean onBeforeOpenMenu(ObjectNode eventDetail) {
return columnDynamicContentHandler.test(item, column);
}
- if (dynamicContentHandler != null) {
+ if (getDynamicContentHandler() != null) {
final T item = grid.getDataCommunicator().getKeyMapper().get(key);
- return dynamicContentHandler.test(item);
+ return getDynamicContentHandler().test(item);
}
return super.onBeforeOpenMenu(eventDetail);
From 855202689d981bcd5938a2655c60a7a4b3eb2a18 Mon Sep 17 00:00:00 2001
From: "totally-not-ai[bot]"
<290682512+totally-not-ai[bot]@users.noreply.github.com>
Date: Sun, 4 Oct 2026 06:17:21 +0000
Subject: [PATCH 5/7] feat: add getter for column-aware grid context menu
dynamic content handler
Co-Authored-By: Claude Opus 5.5
---
.../grid/contextmenu/GridContextMenu.java | 22 +++++++++++++++----
.../grid/contextmenu/GridContextMenuTest.java | 16 ++++++++++++--
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
index ea6c58efa07..7c17223d305 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
@@ -253,10 +253,9 @@ public Registration addGridContextMenuOpenedListener(
* receives the column was set with
* {@link #setDynamicContentHandler(SerializableBiPredicate)}.
* @since 4.1
- * @deprecated Use
- * {@link #setDynamicContentHandler(SerializableBiPredicate)} to
- * set a handler that also receives the clicked column. There is
- * no replacement for getting the handler.
+ * @deprecated Use {@link #getColumnDynamicContentHandler()} together with
+ * {@link #setDynamicContentHandler(SerializableBiPredicate)},
+ * which also receives the clicked column.
*/
@Deprecated(since = "25.4", forRemoval = true)
public SerializablePredicate getDynamicContentHandler() {
@@ -339,6 +338,21 @@ public void setDynamicContentHandler(
this.dynamicContentHandler = null;
}
+ /**
+ * Gets the callback function that is executed before the context menu is
+ * opened, and that receives both the clicked item and the clicked column.
+ *
+ * @return the callback function that is executed before opening the context
+ * menu, or {@code null} if not specified or if an item-only handler
+ * was set with
+ * {@link #setDynamicContentHandler(SerializablePredicate)}.
+ * @see #setDynamicContentHandler(SerializableBiPredicate)
+ * @since 25.4
+ */
+ public SerializableBiPredicate> getColumnDynamicContentHandler() {
+ return columnDynamicContentHandler;
+ }
+
/**
* {@inheritDoc}
*
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
index be5a5d1d87f..7c5db7bc567 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
@@ -34,6 +34,8 @@
import com.vaadin.flow.component.grid.contextmenu.GridContextMenu.GridContextMenuItemClickEvent;
import com.vaadin.flow.component.html.NativeButton;
import com.vaadin.flow.dom.DomEvent;
+import com.vaadin.flow.function.SerializableBiPredicate;
+import com.vaadin.flow.function.SerializablePredicate;
import com.vaadin.flow.function.SerializableRunnable;
import com.vaadin.flow.internal.JacksonUtils;
import com.vaadin.flow.internal.nodefeature.ElementListenerMap;
@@ -199,8 +201,18 @@ void setDynamicContentHandler_replacesHandlerOfOtherType() {
GridContextMenu contextMenu = new Grid()
.addContextMenu();
- contextMenu.setDynamicContentHandler(item -> true);
- contextMenu.setDynamicContentHandler((item, column) -> true);
+ SerializablePredicate itemHandler = item -> true;
+ SerializableBiPredicate> columnHandler = (
+ item, column) -> true;
+
+ contextMenu.setDynamicContentHandler(itemHandler);
+ Assertions.assertSame(itemHandler,
+ contextMenu.getDynamicContentHandler());
+ Assertions.assertNull(contextMenu.getColumnDynamicContentHandler());
+
+ contextMenu.setDynamicContentHandler(columnHandler);
+ Assertions.assertSame(columnHandler,
+ contextMenu.getColumnDynamicContentHandler());
Assertions.assertNull(contextMenu.getDynamicContentHandler());
AtomicReference called = new AtomicReference<>(false);
From 2e58f26506931978aeb44e06769b61a15b77044a Mon Sep 17 00:00:00 2001
From: "totally-not-ai[bot]"
<290682512+totally-not-ai[bot]@users.noreply.github.com>
Date: Sun, 4 Oct 2026 06:18:00 +0000
Subject: [PATCH 6/7] test: assert item-only handler clears column-aware
handler getter
Co-Authored-By: Claude Opus 5.5
---
.../flow/component/grid/contextmenu/GridContextMenuTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
index 7c5db7bc567..d2477bb5bc1 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
@@ -208,7 +208,6 @@ void setDynamicContentHandler_replacesHandlerOfOtherType() {
contextMenu.setDynamicContentHandler(itemHandler);
Assertions.assertSame(itemHandler,
contextMenu.getDynamicContentHandler());
- Assertions.assertNull(contextMenu.getColumnDynamicContentHandler());
contextMenu.setDynamicContentHandler(columnHandler);
Assertions.assertSame(columnHandler,
@@ -221,6 +220,7 @@ void setDynamicContentHandler_replacesHandlerOfOtherType() {
return false;
});
contextMenu.setDynamicContentHandler(item -> false);
+ Assertions.assertNull(contextMenu.getColumnDynamicContentHandler());
fireBeforeOpenEvent((Grid>) contextMenu.getTarget(), "", "", "");
Assertions.assertFalse(called.get());
}
From 72db0d7b8198b5fac86f8177793a81c5e07de8ef Mon Sep 17 00:00:00 2001
From: "totally-not-ai[bot]"
<290682512+totally-not-ai[bot]@users.noreply.github.com>
Date: Sun, 4 Oct 2026 07:05:42 +0000
Subject: [PATCH 7/7] refactor: pass a context record to grid context menu
dynamic content provider
Replace the (item, column) setDynamicContentHandler overload with
setDynamicContentProvider, which receives a DynamicContentContext record.
New context information can then be added later without new overloads.
Co-Authored-By: Claude Opus 5.5
---
.../DynamicContextMenuGridPage.java | 15 +--
.../contextmenu/DynamicContextMenuGridIT.java | 4 +-
.../grid/contextmenu/GridContextMenu.java | 108 +++++++++++-------
.../grid/contextmenu/GridContextMenuTest.java | 46 ++++----
4 files changed, 94 insertions(+), 79 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java
index b162d8c3ff5..7087ef275e6 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridPage.java
@@ -27,7 +27,7 @@ public class DynamicContextMenuGridPage extends Div {
public DynamicContextMenuGridPage() {
gridWithDynamicContextMenu();
- gridWithColumnDynamicContextMenu();
+ gridWithDynamicContentProvider();
}
private void gridWithDynamicContextMenu() {
@@ -55,7 +55,7 @@ private void gridWithDynamicContextMenu() {
add(grid);
}
- private void gridWithColumnDynamicContextMenu() {
+ private void gridWithDynamicContentProvider() {
final Grid grid = new Grid<>();
Grid.Column nameColumn = grid.addColumn(Person::getFirstName)
.setHeader("Name");
@@ -66,17 +66,18 @@ private void gridWithColumnDynamicContextMenu() {
GridContextMenu contextMenu = grid.addContextMenu();
- contextMenu.setDynamicContentHandler((person, column) -> {
+ contextMenu.setDynamicContentProvider(context -> {
+ Person person = context.item();
contextMenu.removeAll();
if (person != null) {
- contextMenu.addItem(
- column == nameColumn ? "Call " + person.getFirstName()
- : "Age " + person.getAge());
+ contextMenu.addItem(context.column() == nameColumn
+ ? "Call " + person.getFirstName()
+ : "Age " + person.getAge());
}
return person != null;
});
- grid.setId("grid-with-column-dynamic-context-menu");
+ grid.setId("grid-with-dynamic-content-provider");
add(grid);
}
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java
index c07b88820e2..6c95c65b9a1 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/contextmenu/DynamicContextMenuGridIT.java
@@ -77,9 +77,9 @@ public void shouldOpenContextMenuWhenClickingOnTheEdgeOfCell() {
}
@Test
- public void columnDynamicContentHandler_menuContentDependsOnClickedColumn() {
+ public void dynamicContentProvider_menuContentDependsOnClickedColumn() {
GridElement columnGrid = $(GridElement.class)
- .id("grid-with-column-dynamic-context-menu");
+ .id("grid-with-dynamic-content-provider");
columnGrid.getCell(5, 1).contextClick();
verifyOpened();
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
index 7c17223d305..2d1ca82e105 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenu.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.flow.component.grid.contextmenu;
+import java.io.Serializable;
import java.util.List;
import java.util.Optional;
@@ -25,7 +26,6 @@
import com.vaadin.flow.component.contextmenu.MenuManager;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.function.SerializableBiFunction;
-import com.vaadin.flow.function.SerializableBiPredicate;
import com.vaadin.flow.function.SerializablePredicate;
import com.vaadin.flow.function.SerializableRunnable;
import com.vaadin.flow.shared.Registration;
@@ -45,7 +45,7 @@ public class GridContextMenu extends
implements HasGridMenuItems {
private SerializablePredicate dynamicContentHandler;
- private SerializableBiPredicate> columnDynamicContentHandler;
+ private SerializablePredicate> dynamicContentProvider;
/**
* Event that is fired when a {@link GridMenuItem} is clicked inside a
@@ -137,6 +137,27 @@ public Optional getColumnId() {
}
+ /**
+ * The context of a context-click on a {@link Grid}, passed to the
+ * {@link #setDynamicContentProvider(SerializablePredicate) dynamic content
+ * provider}.
+ *
+ * @param item
+ * the item in the Grid that was the target of the context-click,
+ * or {@code null} if the context-click didn't target any item
+ * (eg. if targeting a header)
+ * @param column
+ * the column in the Grid that was the target of the
+ * context-click, or {@code null} if the context-click didn't
+ * target any application column (eg. selection column)
+ * @param
+ * the grid bean type
+ * @since 25.4
+ */
+ public record DynamicContentContext(T item,
+ Grid.Column column) implements Serializable {
+ }
+
/**
* Creates an empty context menu to be used with a Grid.
*/
@@ -249,12 +270,12 @@ public Registration addGridContextMenuOpenedListener(
*
*
* @return the callback function that is executed before opening the context
- * menu, or {@code null} if not specified or if a handler that also
- * receives the column was set with
- * {@link #setDynamicContentHandler(SerializableBiPredicate)}.
+ * menu, or {@code null} if not specified or if a dynamic content
+ * provider was set with
+ * {@link #setDynamicContentProvider(SerializablePredicate)}.
* @since 4.1
- * @deprecated Use {@link #getColumnDynamicContentHandler()} together with
- * {@link #setDynamicContentHandler(SerializableBiPredicate)},
+ * @deprecated Use {@link #getDynamicContentProvider()} together with
+ * {@link #setDynamicContentProvider(SerializablePredicate)},
* which also receives the clicked column.
*/
@Deprecated(since = "25.4", forRemoval = true)
@@ -276,40 +297,55 @@ public SerializablePredicate getDynamicContentHandler() {
* will be opened.
*
*
- * Replaces any handler set with
- * {@link #setDynamicContentHandler(SerializableBiPredicate)}.
+ * Replaces any provider set with
+ * {@link #setDynamicContentProvider(SerializablePredicate)}.
*
*
* @param dynamicContentHandler
* the callback function that will be executed before opening the
* context menu.
* @since 4.1
- * @deprecated Use
- * {@link #setDynamicContentHandler(SerializableBiPredicate)}
+ * @deprecated Use {@link #setDynamicContentProvider(SerializablePredicate)}
* instead, which also receives the clicked column.
*/
@Deprecated(since = "25.4", forRemoval = true)
public void setDynamicContentHandler(
SerializablePredicate dynamicContentHandler) {
this.dynamicContentHandler = dynamicContentHandler;
- this.columnDynamicContentHandler = null;
+ this.dynamicContentProvider = null;
}
/**
- * Sets a callback that is executed before the context menu is opened, and
- * that receives both the clicked item and the clicked column.
+ * Gets the callback function that is executed before the context menu is
+ * opened to dynamically provide its contents.
+ *
+ * @return the callback function that is executed before opening the context
+ * menu, or {@code null} if not specified or if a handler was set
+ * with {@link #setDynamicContentHandler(SerializablePredicate)}.
+ * @see #setDynamicContentProvider(SerializablePredicate)
+ * @since 25.4
+ */
+ public SerializablePredicate> getDynamicContentProvider() {
+ return dynamicContentProvider;
+ }
+
+ /**
+ * Sets a callback that is executed before the context menu is opened to
+ * dynamically provide its contents.
*
*
- * Use this to build context menus whose contents depend on the column that
- * was clicked, for example:
+ * The callback receives a {@link DynamicContentContext} with the clicked
+ * item and column. This is useful when the context menu items depend on
+ * what was clicked, for example:
*
*
*
- * contextMenu.setDynamicContentHandler((person, column) -> {
+ * contextMenu.setDynamicContentProvider(context -> {
* contextMenu.removeAll();
- * if (column == nameColumn) {
+ * Person person = context.item();
+ * if (context.column() == nameColumn) {
* contextMenu.addItem("Call", e -> call(person));
- * } else if (column == addressColumn) {
+ * } else if (context.column() == addressColumn) {
* contextMenu.addItem("Show on map", e -> showOnMap(person));
* }
* return true;
@@ -317,42 +353,25 @@ public void setDynamicContentHandler(
*
*
*
- * The item is {@code null} if the context-click didn't target an item (eg.
- * a header). The column is {@code null} if the context-click didn't target
- * an application column (eg. the selection column). The boolean return
- * value of this callback specifies if the context menu will be opened.
+ * The boolean return value of this callback specifies if the context menu
+ * will be opened.
*
*
* Replaces any handler set with
* {@link #setDynamicContentHandler(SerializablePredicate)}.
*
*
- * @param dynamicContentHandler
+ * @param dynamicContentProvider
* the callback function that will be executed before opening the
* context menu, or {@code null} to remove it
* @since 25.4
*/
- public void setDynamicContentHandler(
- SerializableBiPredicate> dynamicContentHandler) {
- this.columnDynamicContentHandler = dynamicContentHandler;
+ public void setDynamicContentProvider(
+ SerializablePredicate> dynamicContentProvider) {
+ this.dynamicContentProvider = dynamicContentProvider;
this.dynamicContentHandler = null;
}
- /**
- * Gets the callback function that is executed before the context menu is
- * opened, and that receives both the clicked item and the clicked column.
- *
- * @return the callback function that is executed before opening the context
- * menu, or {@code null} if not specified or if an item-only handler
- * was set with
- * {@link #setDynamicContentHandler(SerializablePredicate)}.
- * @see #setDynamicContentHandler(SerializableBiPredicate)
- * @since 25.4
- */
- public SerializableBiPredicate> getColumnDynamicContentHandler() {
- return columnDynamicContentHandler;
- }
-
/**
* {@inheritDoc}
*
@@ -371,11 +390,12 @@ protected boolean onBeforeOpenMenu(ObjectNode eventDetail) {
grid.getElement().setProperty("_contextMenuTargetItemKey", key);
grid.getElement().setProperty("_contextMenuTargetColumnId", columnId);
- if (columnDynamicContentHandler != null) {
+ if (dynamicContentProvider != null) {
final T item = grid.getDataCommunicator().getKeyMapper().get(key);
final Grid.Column column = getColumnByInternalId(grid,
eventDetail.get("internalColumnId").asString());
- return columnDynamicContentHandler.test(item, column);
+ return dynamicContentProvider
+ .test(new DynamicContentContext<>(item, column));
}
if (getDynamicContentHandler() != null) {
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
index d2477bb5bc1..3c04c752759 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/contextmenu/GridContextMenuTest.java
@@ -34,7 +34,6 @@
import com.vaadin.flow.component.grid.contextmenu.GridContextMenu.GridContextMenuItemClickEvent;
import com.vaadin.flow.component.html.NativeButton;
import com.vaadin.flow.dom.DomEvent;
-import com.vaadin.flow.function.SerializableBiPredicate;
import com.vaadin.flow.function.SerializablePredicate;
import com.vaadin.flow.function.SerializableRunnable;
import com.vaadin.flow.internal.JacksonUtils;
@@ -166,61 +165,56 @@ void dynamicContentHandler_targetColumnIdIsUpdatedBeforeHandlerRuns() {
}
@Test
- void columnDynamicContentHandler_receivesClickedItemAndColumn() {
+ void dynamicContentProvider_receivesClickedItemAndColumn() {
Grid grid = new Grid<>();
grid.setItems("foo", "bar");
Grid.Column first = grid.addColumn(item -> item);
Grid.Column second = grid.addColumn(item -> item);
GridContextMenu contextMenu = grid.addContextMenu();
- AtomicReference itemInHandler = new AtomicReference<>();
- AtomicReference> columnInHandler = new AtomicReference<>();
- contextMenu.setDynamicContentHandler((item, column) -> {
- itemInHandler.set(item);
- columnInHandler.set(column);
+ AtomicReference> contextInProvider = new AtomicReference<>();
+ contextMenu.setDynamicContentProvider(context -> {
+ contextInProvider.set(context);
return false;
});
String barKey = grid.getDataCommunicator().getKeyMapper().key("bar");
fireBeforeOpenEvent(grid, barKey, "", getInternalId(second));
- Assertions.assertEquals("bar", itemInHandler.get());
- Assertions.assertSame(second, columnInHandler.get());
+ Assertions.assertEquals("bar", contextInProvider.get().item());
+ Assertions.assertSame(second, contextInProvider.get().column());
fireBeforeOpenEvent(grid, "", "", getInternalId(first));
- Assertions.assertNull(itemInHandler.get());
- Assertions.assertSame(first, columnInHandler.get());
+ Assertions.assertNull(contextInProvider.get().item());
+ Assertions.assertSame(first, contextInProvider.get().column());
// Not an application column, e.g. the selection column
fireBeforeOpenEvent(grid, barKey, "", "");
- Assertions.assertEquals("bar", itemInHandler.get());
- Assertions.assertNull(columnInHandler.get());
+ Assertions.assertEquals("bar", contextInProvider.get().item());
+ Assertions.assertNull(contextInProvider.get().column());
}
@Test
- void setDynamicContentHandler_replacesHandlerOfOtherType() {
+ void dynamicContentProviderAndHandler_replaceEachOther() {
GridContextMenu contextMenu = new Grid()
.addContextMenu();
+ SerializablePredicate handler = item -> true;
+ SerializablePredicate> provider = context -> true;
- SerializablePredicate itemHandler = item -> true;
- SerializableBiPredicate> columnHandler = (
- item, column) -> true;
+ contextMenu.setDynamicContentHandler(handler);
+ Assertions.assertSame(handler, contextMenu.getDynamicContentHandler());
- contextMenu.setDynamicContentHandler(itemHandler);
- Assertions.assertSame(itemHandler,
- contextMenu.getDynamicContentHandler());
-
- contextMenu.setDynamicContentHandler(columnHandler);
- Assertions.assertSame(columnHandler,
- contextMenu.getColumnDynamicContentHandler());
+ contextMenu.setDynamicContentProvider(provider);
+ Assertions.assertSame(provider,
+ contextMenu.getDynamicContentProvider());
Assertions.assertNull(contextMenu.getDynamicContentHandler());
AtomicReference called = new AtomicReference<>(false);
- contextMenu.setDynamicContentHandler((item, column) -> {
+ contextMenu.setDynamicContentProvider(context -> {
called.set(true);
return false;
});
contextMenu.setDynamicContentHandler(item -> false);
- Assertions.assertNull(contextMenu.getColumnDynamicContentHandler());
+ Assertions.assertNull(contextMenu.getDynamicContentProvider());
fireBeforeOpenEvent((Grid>) contextMenu.getTarget(), "", "", "");
Assertions.assertFalse(called.get());
}