diff options
author | Teemu Suo-Anttila <tsuoanttila@users.noreply.github.com> | 2017-03-15 14:00:50 +0200 |
---|---|---|
committer | Teemu Suo-Anttila <tsuoanttila@users.noreply.github.com> | 2017-03-16 16:21:24 +0200 |
commit | f6888557f39f697a1911b2f8cf53dee3bfa55a65 (patch) | |
tree | 227d5bd67caa7fee2cc82bb499d2e24e29cde947 | |
parent | 188884d4c2309873e7e7144face9fb0053b18a6f (diff) | |
download | vaadin-framework-f6888557f39f697a1911b2f8cf53dee3bfa55a65.tar.gz vaadin-framework-f6888557f39f697a1911b2f8cf53dee3bfa55a65.zip |
Allow changing renderers after column creation (#8841)
Closes #8250
6 files changed, 217 insertions, 3 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/ColumnConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/ColumnConnector.java index d619b50b5d..149ef4c1f9 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/ColumnConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/ColumnConnector.java @@ -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); diff --git a/documentation/components/components-grid.asciidoc b/documentation/components/components-grid.asciidoc index e35f2b0aac..6a18a54897 100644 --- a/documentation/components/components-grid.asciidoc +++ b/documentation/components/components-grid.asciidoc @@ -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: diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 564ab6f073..30c49cffa6 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -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; @@ -1775,6 +1776,34 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents, } /** + * 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. * * @return the grid that this column belongs to, or <code>null</code> if @@ -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; diff --git a/tests/screenshots b/tests/screenshots -Subproject f11893e9d3a12945497d47ae0ed0d45d0103ccc +Subproject c87c64ec9448df91164efd72cfe62791c148e0c 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 index 0000000000..b73383d22b --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridRendererSwitch.java @@ -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 index 0000000000..1fd775b58a --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridRendererSwitchTest.java @@ -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(); + } + +} |