} element.
*
- *
- * Every added column sends data to the client side regardless of its
- * visibility state. Don't add a new column at all or use
- * {@link GridPro#removeColumn(Column)} to avoid sending extra data.
- *
* @param
* type of the underlying grid this column is compatible with
*/
From 361ccded19a8d83fa7c68bc97997d1101bdce245 Mon Sep 17 00:00:00 2001
From: ugur-vaadin
Date: Thu, 7 Nov 2024 23:28:08 +0200
Subject: [PATCH 2/7] fix: remove unnecessary line
---
.../src/main/java/com/vaadin/flow/component/grid/Grid.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
index 85047b9625..40dde15a76 100755
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
@@ -531,7 +531,6 @@ public Column setRenderer(Renderer renderer) {
this.renderer = Objects.requireNonNull(renderer,
"Renderer must not be null.");
clearRendering();
- rendererSetupScheduled = true;
getElement().getNode()
.runWhenAttached(ui -> scheduleRendererSetup());
addAttachListener(e -> scheduleRendererSetup());
From 4128359be28bbc55c4052f15feca29e2686a9c7f Mon Sep 17 00:00:00 2001
From: ugur-vaadin
Date: Fri, 8 Nov 2024 15:26:50 +0200
Subject: [PATCH 3/7] fix: send items only once to the client
---
.../com/vaadin/flow/component/grid/Grid.java | 1 -
.../grid/GridHiddenColumnRenderingTest.java | 37 +++++++++++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
index 40dde15a76..a030159d68 100755
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
@@ -534,7 +534,6 @@ public Column setRenderer(Renderer renderer) {
getElement().getNode()
.runWhenAttached(ui -> scheduleRendererSetup());
addAttachListener(e -> scheduleRendererSetup());
- getGrid().getDataCommunicator().reset();
return this;
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
index bd617dcc19..c13b7e865a 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
@@ -28,6 +28,7 @@
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.NativeButton;
+import com.vaadin.flow.data.provider.DataProvider;
import com.vaadin.flow.data.renderer.LitRenderer;
import com.vaadin.flow.data.renderer.Renderer;
import com.vaadin.flow.function.ValueProvider;
@@ -218,6 +219,42 @@ public void initiallyHiddenColumnWithCustomRenderer_detachAndReattachGrid_render
column);
}
+ @Test
+ public void columnWithCustomRenderer_setAnotherRenderer_onlyNewRendererCalled() {
+ Grid.Column column = addColumnWithCustomRenderer();
+ fakeClientCommunication();
+ callCount.set(0);
+ AtomicInteger newRendererCallCount = new AtomicInteger(0);
+ Renderer newRenderer = LitRenderer
+ . of("${item.displayName}")
+ .withProperty("displayName", s -> {
+ newRendererCallCount.incrementAndGet();
+ return s;
+ });
+ column.setRenderer(newRenderer);
+ fakeClientCommunication();
+ Assert.assertEquals(0, callCount.get());
+ Assert.assertEquals(ITEM_COUNT, newRendererCallCount.get());
+ }
+
+ @Test
+ public void addColumn_itemsSentOnlyOnce() {
+ List items = getItems();
+ AtomicInteger fetchCount = new AtomicInteger(0);
+ DataProvider dataProvider = DataProvider
+ .fromCallbacks(query -> {
+ fetchCount.incrementAndGet();
+ return items.stream().skip(query.getOffset())
+ .limit(query.getLimit());
+ }, query -> items.size());
+ grid.setDataProvider(dataProvider);
+ fakeClientCommunication();
+ fetchCount.set(0);
+ addColumnWithValueProvider();
+ fakeClientCommunication();
+ Assert.assertEquals(1, fetchCount.get());
+ }
+
private Grid.Column addColumnWithValueProvider() {
return grid.addColumn(getValueProvider());
}
From 9959a86b677a329954cd0fb963eedabde3d22c2b Mon Sep 17 00:00:00 2001
From: ugur-vaadin
Date: Mon, 11 Nov 2024 23:02:48 +0200
Subject: [PATCH 4/7] refactor: patch data generator instead of scheduling
renderer
---
.../com/vaadin/flow/component/grid/Grid.java | 125 +++++++++---------
.../grid/GridHiddenColumnRenderingTest.java | 16 +--
2 files changed, 71 insertions(+), 70 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
index a030159d68..75fa35c2ba 100755
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
@@ -444,7 +444,6 @@ public static class Column extends AbstractColumn> {
private String columnKey; // defined and used by the user
private boolean sortingEnabled;
- private boolean rendererSetupScheduled;
private Component editorComponent;
private EditorRenderer editorRenderer;
@@ -485,8 +484,38 @@ public Column(Grid grid, String columnId, Renderer renderer) {
super(grid);
Objects.requireNonNull(renderer);
this.columnInternalId = columnId;
+ this.renderer = renderer;
+
comparator = (a, b) -> 0;
- setRenderer(renderer);
+
+ rendering = renderer.render(getElement(), (KeyMapper) getGrid()
+ .getDataCommunicator().getKeyMapper());
+
+ Optional> dataGenerator = rendering
+ .getDataGenerator();
+
+ if (dataGenerator.isPresent()) {
+ var generator = dataGenerator.get();
+ DataGenerator conditionalDataGenerator = (item,
+ jsonObject) -> {
+ if (Column.this.isVisible()) {
+ generator.generateData(item, jsonObject);
+ }
+ };
+
+ columnDataGeneratorRegistration = grid
+ .addDataGenerator(conditionalDataGenerator);
+ }
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ boolean resetDataCommunicator = visible && !isVisible();
+ super.setVisible(visible);
+ if (resetDataCommunicator) {
+ getGrid().getDataCommunicator().reset();
+
+ }
}
protected void destroyDataGenerators() {
@@ -530,10 +559,33 @@ public Renderer getRenderer() {
public Column setRenderer(Renderer renderer) {
this.renderer = Objects.requireNonNull(renderer,
"Renderer must not be null.");
- clearRendering();
- getElement().getNode()
- .runWhenAttached(ui -> scheduleRendererSetup());
- addAttachListener(e -> scheduleRendererSetup());
+
+ destroyDataGenerators();
+ if (rendering != null) {
+ rendering.getRegistration().remove();
+ }
+
+ rendering = renderer.render(getElement(), (KeyMapper) getGrid()
+ .getDataCommunicator().getKeyMapper());
+
+ columnDataGeneratorRegistration = rendering.getDataGenerator()
+ .map(dataGenerator -> grid
+ .addDataGenerator((DataGenerator) dataGenerator))
+ .orElse(null);
+
+ // The editor renderer is a wrapper around the regular renderer, so
+ // we need to apply it again afterwards
+ if (editorRenderer != null) {
+ Rendering editorRendering = editorRenderer
+ .render(getElement(), null);
+ editorDataGeneratorRegistration = editorRendering
+ .getDataGenerator()
+ .map(dataGenerator -> grid.addDataGenerator(
+ (DataGenerator) dataGenerator))
+ .orElse(null);
+ }
+
+ getGrid().getDataCommunicator().reset();
return this;
}
@@ -1133,18 +1185,6 @@ public Column setRowHeader(boolean rowHeader) {
return this;
}
- @Override
- public void setVisible(boolean visible) {
- boolean isInitiallyVisible = isVisible();
- super.setVisible(visible);
- if (isInitiallyVisible && !visible) {
- clearRendering();
- }
- if (!isInitiallyVisible && visible) {
- scheduleRendererSetup();
- }
- }
-
@Override
protected Column> getBottomLevelColumn() {
return this;
@@ -1154,54 +1194,15 @@ protected Column> getBottomLevelColumn() {
private void setupColumnEditor() {
editorRenderer = new EditorRenderer<>((Editor) grid.getEditor(),
columnInternalId);
- setupEditorRenderer();
- }
- private void setupRenderer() {
- if (renderer == null) {
- return;
- }
- rendering = renderer.render(getElement(), (KeyMapper) getGrid()
- .getDataCommunicator().getKeyMapper());
- columnDataGeneratorRegistration = rendering.getDataGenerator()
- .map(dataGenerator -> grid
- .addDataGenerator((DataGenerator) dataGenerator))
- .orElse(null);
- grid.getDataProvider().refreshAll();
- }
-
- private void setupEditorRenderer() {
- if (editorRenderer == null) {
- return;
- }
Rendering editorRendering = editorRenderer.render(getElement(),
null);
- editorDataGeneratorRegistration = editorRendering.getDataGenerator()
- .map(dataGenerator -> grid
- .addDataGenerator((DataGenerator) dataGenerator))
- .orElse(null);
- }
- private void scheduleRendererSetup() {
- if (rendererSetupScheduled) {
- return;
- }
- rendererSetupScheduled = true;
- getUI().ifPresent(ui -> ui.beforeClientResponse(this, ctx -> {
- if (rendererSetupScheduled && isVisible()) {
- setupRenderer();
- // The editor renderer is a wrapper around the regular
- // renderer, so we need to apply it again afterward.
- setupEditorRenderer();
- }
- rendererSetupScheduled = false;
- }));
- }
-
- private void clearRendering() {
- destroyDataGenerators();
- if (rendering != null) {
- rendering.getRegistration().remove();
+ Optional> dataGenerator = editorRendering
+ .getDataGenerator();
+ if (dataGenerator.isPresent()) {
+ editorDataGeneratorRegistration = grid
+ .addDataGenerator((DataGenerator) dataGenerator.get());
}
}
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
index c13b7e865a..144eeaf160 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
@@ -89,9 +89,9 @@ public void initiallyHiddenColumnWithValueProvider_setVisible_rendererCalledOnce
}
@Test
- public void columnWithValueProvider_toggleHiddenTwiceInRoundTrip_rendererCalledOncePerItem() {
+ public void columnWithValueProvider_toggleHiddenTwiceInRoundTrip_rendererCalledAtMostOncePerItem() {
Grid.Column column = addColumnWithValueProvider();
- initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
+ initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
column);
}
@@ -128,9 +128,9 @@ public void initiallyHiddenComponentColumn_setVisible_rendererCalledOncePerItem(
}
@Test
- public void componentColumn_toggleHiddenTwiceInRoundTrip_rendererCalledOncePerItem() {
+ public void componentColumn_toggleHiddenTwiceInRoundTrip_rendererCalledAtMostOncePerItem() {
Grid.Column column = addComponentColumn();
- initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
+ initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
column);
}
@@ -167,9 +167,9 @@ public void initiallyHiddenColumnWithCustomRenderer_setVisible_rendererCalledOnc
}
@Test
- public void columnWithCustomRenderer_toggleHiddenTwiceInRoundTrip_rendererCalledOncePerItem() {
+ public void columnWithCustomRenderer_toggleHiddenTwiceInRoundTrip_rendererCalledAtMostOncePerItem() {
Grid.Column column = addColumnWithCustomRenderer();
- initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
+ initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
column);
}
@@ -316,14 +316,14 @@ private void initiallyHiddenColumn_setVisible_assertRendererCalledOncePerItem(
Assert.assertEquals(ITEM_COUNT, callCount.get());
}
- private void initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
+ private void initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
Grid.Column column) {
fakeClientCommunication();
column.setVisible(false);
column.setVisible(true);
callCount.set(0);
fakeClientCommunication();
- Assert.assertEquals(ITEM_COUNT, callCount.get());
+ Assert.assertTrue(callCount.get() <= ITEM_COUNT);
}
private void initiallyHiddenColumn_toggleHiddenTwiceInRoundTrip_assertRendererNotCalled(
From c359c25ef9f1bc232854a1d16537f774d1203afb Mon Sep 17 00:00:00 2001
From: ugur-vaadin
Date: Mon, 11 Nov 2024 23:04:36 +0200
Subject: [PATCH 5/7] chore: remove extra empty lines
---
.../src/main/java/com/vaadin/flow/component/grid/Grid.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
index 75fa35c2ba..ea28967d38 100755
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
@@ -502,7 +502,6 @@ public Column(Grid grid, String columnId, Renderer renderer) {
generator.generateData(item, jsonObject);
}
};
-
columnDataGeneratorRegistration = grid
.addDataGenerator(conditionalDataGenerator);
}
@@ -514,7 +513,6 @@ public void setVisible(boolean visible) {
super.setVisible(visible);
if (resetDataCommunicator) {
getGrid().getDataCommunicator().reset();
-
}
}
From 982bb82065db7cc433083c629d62fa4fa139fb41 Mon Sep 17 00:00:00 2001
From: ugur-vaadin
Date: Tue, 12 Nov 2024 10:29:40 +0200
Subject: [PATCH 6/7] fix: override all methods when patching data generator
---
.../com/vaadin/flow/component/grid/Grid.java | 29 ++++++++++++++++---
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
index ea28967d38..546688c2d4 100755
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/Grid.java
@@ -496,10 +496,31 @@ public Column(Grid grid, String columnId, Renderer renderer) {
if (dataGenerator.isPresent()) {
var generator = dataGenerator.get();
- DataGenerator conditionalDataGenerator = (item,
- jsonObject) -> {
- if (Column.this.isVisible()) {
- generator.generateData(item, jsonObject);
+
+ // Use an anonymous class instead of Lambda to prevent potential
+ // deserialization issues when used with Grid
+ // see https://github.com/vaadin/flow-components/issues/6256
+ var conditionalDataGenerator = new DataGenerator() {
+ @Override
+ public void generateData(T item, JsonObject jsonObject) {
+ if (Column.this.isVisible()) {
+ generator.generateData(item, jsonObject);
+ }
+ }
+
+ @Override
+ public void destroyData(T item) {
+ generator.destroyData(item);
+ }
+
+ @Override
+ public void destroyAllData() {
+ generator.destroyAllData();
+ }
+
+ @Override
+ public void refreshData(T item) {
+ generator.refreshData(item);
}
};
columnDataGeneratorRegistration = grid
From 337eab26fd29f714113ad23f04b1beeccaabce37 Mon Sep 17 00:00:00 2001
From: ugur-vaadin
Date: Tue, 12 Nov 2024 11:06:34 +0200
Subject: [PATCH 7/7] test: revert unit test asserions
---
.../grid/GridHiddenColumnRenderingTest.java | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
index 144eeaf160..c13b7e865a 100644
--- a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridHiddenColumnRenderingTest.java
@@ -89,9 +89,9 @@ public void initiallyHiddenColumnWithValueProvider_setVisible_rendererCalledOnce
}
@Test
- public void columnWithValueProvider_toggleHiddenTwiceInRoundTrip_rendererCalledAtMostOncePerItem() {
+ public void columnWithValueProvider_toggleHiddenTwiceInRoundTrip_rendererCalledOncePerItem() {
Grid.Column column = addColumnWithValueProvider();
- initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
+ initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
column);
}
@@ -128,9 +128,9 @@ public void initiallyHiddenComponentColumn_setVisible_rendererCalledOncePerItem(
}
@Test
- public void componentColumn_toggleHiddenTwiceInRoundTrip_rendererCalledAtMostOncePerItem() {
+ public void componentColumn_toggleHiddenTwiceInRoundTrip_rendererCalledOncePerItem() {
Grid.Column column = addComponentColumn();
- initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
+ initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
column);
}
@@ -167,9 +167,9 @@ public void initiallyHiddenColumnWithCustomRenderer_setVisible_rendererCalledOnc
}
@Test
- public void columnWithCustomRenderer_toggleHiddenTwiceInRoundTrip_rendererCalledAtMostOncePerItem() {
+ public void columnWithCustomRenderer_toggleHiddenTwiceInRoundTrip_rendererCalledOncePerItem() {
Grid.Column column = addColumnWithCustomRenderer();
- initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
+ initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
column);
}
@@ -316,14 +316,14 @@ private void initiallyHiddenColumn_setVisible_assertRendererCalledOncePerItem(
Assert.assertEquals(ITEM_COUNT, callCount.get());
}
- private void initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledAtMostOncePerItem(
+ private void initiallyVisibleColumn_toggleHiddenTwiceInRoundTrip_assertRendererCalledOncePerItem(
Grid.Column column) {
fakeClientCommunication();
column.setVisible(false);
column.setVisible(true);
callCount.set(0);
fakeClientCommunication();
- Assert.assertTrue(callCount.get() <= ITEM_COUNT);
+ Assert.assertEquals(ITEM_COUNT, callCount.get());
}
private void initiallyHiddenColumn_toggleHiddenTwiceInRoundTrip_assertRendererNotCalled(