diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/it/GridEmptyStatePage.java b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/it/GridEmptyStatePage.java new file mode 100644 index 00000000000..4a37ac8211e --- /dev/null +++ b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/main/java/com/vaadin/flow/component/grid/it/GridEmptyStatePage.java @@ -0,0 +1,32 @@ +package com.vaadin.flow.component.grid.it; + +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.data.bean.Person; +import com.vaadin.flow.router.Route; + +@Route("vaadin-grid/empty-state") +public class GridEmptyStatePage extends Div { + public GridEmptyStatePage() { + var grid = new Grid<>(Person.class); + add(grid); + + // Button to set the empty state content + var setEmptyStateContentButton = new Button("Set empty state content", + event -> grid.setEmptyStateText("Custom empty state content")); + setEmptyStateContentButton.setId("set-empty-state-content"); + + // Button to set the grid items + var setItemsButton = new Button("Set items", event -> grid + .setItems(new Person("John", 20), new Person("Jane", 30))); + setItemsButton.setId("set-items"); + + // Button to clear the grid items + var clearItemsButton = new Button("Clear items", + event -> grid.setItems()); + clearItemsButton.setId("clear-items"); + + add(setEmptyStateContentButton, setItemsButton, clearItemsButton); + } +} diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/it/GridEmptyStateIT.java b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/it/GridEmptyStateIT.java new file mode 100644 index 00000000000..90d651301f1 --- /dev/null +++ b/vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests/src/test/java/com/vaadin/flow/component/grid/it/GridEmptyStateIT.java @@ -0,0 +1,61 @@ +package com.vaadin.flow.component.grid.it; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.NoSuchElementException; + +import com.vaadin.flow.component.button.testbench.ButtonElement; +import com.vaadin.flow.component.grid.testbench.GridElement; +import com.vaadin.flow.testutil.TestPath; +import com.vaadin.tests.AbstractComponentIT; + +@TestPath("vaadin-grid/empty-state") +public class GridEmptyStateIT extends AbstractComponentIT { + private GridElement grid; + private ButtonElement setEmptyStateContentButton; + private ButtonElement clearItemsButton; + private ButtonElement setItemsButton; + + @Before + public void init() { + open(); + grid = $(GridElement.class).first(); + setEmptyStateContentButton = $(ButtonElement.class) + .id("set-empty-state-content"); + clearItemsButton = $(ButtonElement.class).id("clear-items"); + setItemsButton = $(ButtonElement.class).id("set-items"); + } + + @Test + public void getEmptyStateContent_throws() { + Assert.assertThrows("No empty state content was found", + NoSuchElementException.class, + () -> grid.getEmptyStateContent()); + } + + @Test + public void setEmptyStateContent_emptyStateContentDisplayed() { + setEmptyStateContentButton.click(); + var content = grid.getEmptyStateContent(); + Assert.assertEquals("Custom empty state content", content.getText()); + Assert.assertTrue(content.isDisplayed()); + } + + @Test + public void setEmptyStateContent_setItems_emptyStateContentNotDisplayed() { + setEmptyStateContentButton.click(); + setItemsButton.click(); + var content = grid.getEmptyStateContent(); + Assert.assertFalse(content.isDisplayed()); + } + + @Test + public void setEmptyStateContent_setItems_clearItems_emptyStateContentDisplayed() { + setEmptyStateContentButton.click(); + setItemsButton.click(); + clearItemsButton.click(); + var content = grid.getEmptyStateContent(); + Assert.assertTrue(content.isDisplayed()); + } +} 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 0b1dee3de9f..03b3194f3ae 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 @@ -64,6 +64,7 @@ import com.vaadin.flow.component.grid.editor.Editor; import com.vaadin.flow.component.grid.editor.EditorImpl; import com.vaadin.flow.component.grid.editor.EditorRenderer; +import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.page.PendingJavaScriptResult; import com.vaadin.flow.component.shared.SelectionPreservationHandler; import com.vaadin.flow.component.shared.SelectionPreservationMode; @@ -1457,6 +1458,10 @@ public UpdateQueueData getUpdateQueueData() { private PendingJavaScriptResult pendingSorterUpdate; + private static final String EMPTY_STATE_SLOT = "empty-state"; + private Component emptyStateComponent; + private String emptyStateText; + /** * Creates a new instance, with page size of 50. */ @@ -5056,4 +5061,62 @@ private String getUniqueKey(T item) { .map(provider -> provider.apply(item)) .orElse(getDataCommunicator().getKeyMapper().key(item)); } + + /** + * Sets the component to be displayed when the grid is empty. + *
+ * Note: This will also override any empty state content set with + * {@link #setEmptyStateText(String)}. + * + * @param emptyStateComponent + * the component to be displayed when the grid is empty + */ + public void setEmptyStateComponent(Component emptyStateComponent) { + this.emptyStateText = null; + this.emptyStateComponent = emptyStateComponent; + updateEmptyStateContent(); + } + + /** + * Sets the text to be displayed when the grid is empty. + *
+ * Note: This will also override any empty state content set with
+ * {@link #setEmptyStateComponent(Component)}.
+ *
+ * @param emptyStateText
+ * the text to be displayed when the grid is empty
+ */
+ public void setEmptyStateText(String emptyStateText) {
+ this.emptyStateComponent = null;
+ this.emptyStateText = emptyStateText;
+ updateEmptyStateContent();
+ }
+
+ /**
+ * Returns the component that is displayed when the grid is empty.
+ *
+ * @return the component that is displayed when the grid is empty
+ */
+ public Component getEmptyStateComponent() {
+ return emptyStateComponent;
+ }
+
+ /**
+ * Returns the text that is displayed when the grid is empty.
+ *
+ * @return the text that is displayed when the grid is empty
+ */
+ public String getEmptyStateText() {
+ return emptyStateText;
+ }
+
+ private void updateEmptyStateContent() {
+ if (emptyStateComponent != null) {
+ SlotUtils.setSlot(this, EMPTY_STATE_SLOT, emptyStateComponent);
+ } else if (emptyStateText != null) {
+ SlotUtils.setSlot(this, EMPTY_STATE_SLOT, new Span(emptyStateText));
+ } else {
+ SlotUtils.clearSlot(this, EMPTY_STATE_SLOT);
+ }
+ }
}
diff --git a/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridEmptyStateTest.java b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridEmptyStateTest.java
new file mode 100644
index 00000000000..1b72ba4a0e8
--- /dev/null
+++ b/vaadin-grid-flow-parent/vaadin-grid-flow/src/test/java/com/vaadin/flow/component/grid/GridEmptyStateTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2000-2024 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.flow.component.grid;
+
+import java.util.Optional;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.flow.component.html.Div;
+import com.vaadin.flow.dom.Element;
+
+public class GridEmptyStateTest {
+
+ private Grid