]> source.dussan.org Git - vaadin-framework.git/commitdiff
Allow changing renderers after column creation (#8841)
authorTeemu Suo-Anttila <tsuoanttila@users.noreply.github.com>
Wed, 15 Mar 2017 12:00:50 +0000 (14:00 +0200)
committerTeemu Suo-Anttila <tsuoanttila@users.noreply.github.com>
Thu, 16 Mar 2017 14:21:24 +0000 (16:21 +0200)
Closes #8250

client/src/main/java/com/vaadin/client/connectors/grid/ColumnConnector.java
documentation/components/components-grid.asciidoc
server/src/main/java/com/vaadin/ui/Grid.java
tests/screenshots
uitest/src/main/java/com/vaadin/tests/components/grid/GridRendererSwitch.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/grid/GridRendererSwitchTest.java [new file with mode: 0644]

index d619b50b5d985c313d6654ec8186dbc8d201a084..149ef4c1f94c2ac6cbc9acfc5f4e853ca825b6c2 100644 (file)
@@ -73,7 +73,6 @@ public class ColumnConnector extends AbstractExtensionConnector {
                 return null;
             }
         };
-        column.setRenderer(getRendererConnector().getRenderer());
         getParent().addColumn(column, getState().internalId);
     }
 
@@ -92,6 +91,11 @@ public class ColumnConnector extends AbstractExtensionConnector {
         column.setSortable(getState().sortable);
     }
 
+    @OnStateChange("renderer")
+    void updateRenderer() {
+        column.setRenderer(getRendererConnector().getRenderer());
+    }
+
     @OnStateChange("hidingToggleCaption")
     void updateHidingToggleCaption() {
         column.setHidingToggleCaption(getState().hidingToggleCaption);
index e35f2b0aac3990bb77422b3f44bb225c9ca665bc..6a18a548973fe8933c6a3fcae04e6ec030797827 100644 (file)
@@ -403,9 +403,23 @@ You set the column renderer in the [classname]#Grid.Column# object as follows:
 [source, java]
 ----
 // the type of birthYear is a number
-Column<Integer> bornColumn = grid.addColumn(Person:getBirthYear,
+Column<Person, Integer> bornColumn = grid.addColumn(Person:getBirthYear,
       new NumberRenderer("born in %d AD"));
 ----
+
+Changing the renderer during runtime is also possible, but for type safety
+you should store the column reference with data types for doing this.
+When you change the renderer, the content of Grid is refreshed.
+
+[source, java]
+----
+Column<Person, Integer> ageColumn = grid.addColumn(Person::getBirthYear);
+// The default renderer is TextRenderer
+addComponent(new Button("Change renderer", 
+       clickEvent -> ageColumn.setRenderer(new NumberRenderer())
+));
+----
+
 The following renderers are available, as defined in the server-side
 [package]#com.vaadin.ui.renderers# package:
 
index 564ab6f073595de00d5a18d00a9f843d77036a4e..30c49cffa699924b402e37b065373f3c918853af 100644 (file)
@@ -73,6 +73,7 @@ import com.vaadin.server.SerializableFunction;
 import com.vaadin.server.SerializableSupplier;
 import com.vaadin.server.Setter;
 import com.vaadin.server.VaadinServiceClassLoaderUtil;
+import com.vaadin.shared.Connector;
 import com.vaadin.shared.MouseEventDetails;
 import com.vaadin.shared.Registration;
 import com.vaadin.shared.data.DataCommunicatorConstants;
@@ -1774,6 +1775,34 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents,
             return setEditorBinding(binding);
         }
 
+        /**
+         * Sets the Renderer for this Column. Setting the renderer will cause
+         * all currently available row data to be recreated and sent to the
+         * client.
+         *
+         * @param renderer
+         *            the new renderer
+         * @return this column
+         */
+        public Column<T, V> setRenderer(Renderer<? super V> renderer) {
+            Objects.requireNonNull(renderer, "Renderer can't be null");
+
+            // Remove old renderer
+            Connector oldRenderer = getState().renderer;
+            if (oldRenderer != null && oldRenderer instanceof Extension) {
+                removeExtension((Extension) oldRenderer);
+            }
+
+            // Set new renderer
+            getState().renderer = renderer;
+            addExtension(renderer);
+
+            // Trigger redraw
+            getParent().getDataCommunicator().reset();
+
+            return this;
+        }
+
         /**
          * Gets the grid that this column belongs to.
          *
@@ -2302,11 +2331,25 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents,
     public <V> Column<T, V> addColumn(ValueProvider<T, V> valueProvider,
             AbstractRenderer<? super T, ? super V> renderer) {
         String generatedIdentifier = getGeneratedIdentifier();
-        Column<T, V> column = new Column<>(valueProvider, renderer);
+        Column<T, V> column = createColumn(valueProvider, renderer);
         addColumn(generatedIdentifier, column);
         return column;
     }
 
+    /**
+     * Creates a column instance from a value provider and a renderer.
+     *
+     * @param valueProvider
+     *            the value provider
+     * @param renderer
+     *            the renderer
+     * @return a new column instance
+     */
+    protected <V> Column<T, V> createColumn(ValueProvider<T, V> valueProvider,
+            AbstractRenderer<? super T, ? super V> renderer) {
+        return new Column<>(valueProvider, renderer);
+    }
+
     private void addColumn(String identifier, Column<T, ?> column) {
         if (getColumns().contains(column)) {
             return;
index f11893e9d3a12945497d47ae0ed0d45d0103ccce..c87c64ec9448df91164efd72cfe62791c148e0ca 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f11893e9d3a12945497d47ae0ed0d45d0103ccce
+Subproject commit c87c64ec9448df91164efd72cfe62791c148e0ca
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridRendererSwitch.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridRendererSwitch.java
new file mode 100644 (file)
index 0000000..b73383d
--- /dev/null
@@ -0,0 +1,53 @@
+package com.vaadin.tests.components.grid;
+
+import java.util.stream.IntStream;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.renderers.ButtonRenderer;
+import com.vaadin.ui.renderers.TextRenderer;
+
+@Widgetset("com.vaadin.DefaultWidgetSet")
+public class GridRendererSwitch extends AbstractTestUI {
+
+    private boolean textRenderer = true;
+    private boolean reverse = false;
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        Grid<Integer> grid = new Grid<>();
+        Column<Integer, String> column = grid.addColumn(i -> "Foo " + i)
+                .setCaption("Foo");
+        Column<Integer, String> secondColumn = grid.addColumn(i -> "Bar " + i)
+                .setCaption("Bar");
+
+        addComponent(grid);
+        addComponent(new Button("Switch", e -> {
+            if (textRenderer) {
+                ButtonRenderer<Integer> renderer = new ButtonRenderer<>();
+                renderer.addClickListener(event -> Notification
+                        .show("Click on row: " + event.getItem()));
+                column.setRenderer(renderer);
+            } else {
+                column.setRenderer(new TextRenderer());
+            }
+            textRenderer = !textRenderer;
+        }));
+        addComponent(new Button("Reverse", e -> {
+            if (reverse) {
+                grid.setColumnOrder(column, secondColumn);
+            } else {
+                grid.setColumnOrder(secondColumn, column);
+            }
+            reverse = !reverse;
+        }));
+
+        grid.setItems(IntStream.range(0, 10).boxed());
+    }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridRendererSwitchTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridRendererSwitchTest.java
new file mode 100644 (file)
index 0000000..1fd775b
--- /dev/null
@@ -0,0 +1,100 @@
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class GridRendererSwitchTest extends SingleBrowserTest {
+
+    @Test
+    public void testSwitchRenderer() {
+        setDebug(true);
+        openTestURL();
+
+        GridElement grid = $(GridElement.class).first();
+        Assert.assertEquals("Unexpected content in first grid cell", "Foo 0",
+                grid.getCell(0, 0).getAttribute("innerHTML"));
+        ButtonElement button = $(ButtonElement.class).first();
+        button.click();
+        Assert.assertFalse("No button in cell", grid.getCell(0, 0)
+                .findElements(By.tagName("button")).isEmpty());
+        grid.getCell(0, 0).findElement(By.tagName("button")).click();
+        Assert.assertTrue("Notification not shown",
+                isElementPresent(NotificationElement.class));
+        button.click();
+        Assert.assertEquals("Cell should be back to text content.", "Foo 0",
+                grid.getCell(0, 0).getAttribute("innerHTML"));
+
+        assertNoErrorNotifications();
+    }
+
+    @Test
+    public void testSwitchRendererReorderColumns() {
+        setDebug(true);
+        openTestURL();
+
+        GridElement grid = $(GridElement.class).first();
+        Assert.assertEquals("Unexpected content in first grid cell", "Foo 0",
+                grid.getCell(0, 0).getAttribute("innerHTML"));
+        ButtonElement button = $(ButtonElement.class).caption("Switch").first();
+        button.click();
+        ButtonElement reverse = $(ButtonElement.class).caption("Reverse")
+                .first();
+        reverse.click();
+        Assert.assertEquals(
+                "Unexpected content in first grid cell after reorder", "Bar 0",
+                grid.getCell(0, 0).getAttribute("innerHTML"));
+
+        Assert.assertFalse("No button in cell after reversing order", grid
+                .getCell(0, 1).findElements(By.tagName("button")).isEmpty());
+        grid.getCell(0, 1).findElement(By.tagName("button")).click();
+        Assert.assertTrue("Notification not shown",
+                isElementPresent(NotificationElement.class));
+        reverse.click();
+        Assert.assertFalse("No button in cell after restoring original order",
+                grid.getCell(0, 0).findElements(By.tagName("button"))
+                        .isEmpty());
+
+        assertNoErrorNotifications();
+    }
+
+    @Test
+    public void testReorderColumnsSwitchRenderer() {
+        setDebug(true);
+        openTestURL();
+
+        GridElement grid = $(GridElement.class).first();
+        Assert.assertEquals("Unexpected content in first grid cell", "Foo 0",
+                grid.getCell(0, 0).getAttribute("innerHTML"));
+        ButtonElement reverse = $(ButtonElement.class).caption("Reverse")
+                .first();
+
+        reverse.click();
+        Assert.assertEquals(
+                "Unexpected content in first grid cell after reorder", "Bar 0",
+                grid.getCell(0, 0).getAttribute("innerHTML"));
+
+        ButtonElement button = $(ButtonElement.class).caption("Switch").first();
+        button.click();
+
+        Assert.assertFalse(
+                "No button in cell after reversing order and changing renderer",
+                grid.getCell(0, 1).findElements(By.tagName("button"))
+                        .isEmpty());
+        grid.getCell(0, 1).findElement(By.tagName("button")).click();
+        Assert.assertTrue("Notification not shown",
+                isElementPresent(NotificationElement.class));
+
+        button.click();
+        Assert.assertEquals("Cell should be back to text content.", "Foo 0",
+                grid.getCell(0, 1).getAttribute("innerHTML"));
+
+        assertNoErrorNotifications();
+    }
+
+}