diff --git a/pom.xml b/pom.xml
index 195d5a8..fbdfa6f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
org.vaadin.addons.flowingcode
grid-helpers
- 1.3.3-SNAPSHOT
+ 1.4.0-SNAPSHOT
Grid Helpers Add-on
Grid Helpers Add-on for Vaadin Flow
@@ -16,6 +16,8 @@
UTF-8
${project.basedir}/drivers
9.4.36.v20210114
+ 3.8.1
+ 1.0.17
@@ -158,7 +160,7 @@
io.github.bonigarcia
webdrivermanager
- 3.8.1
+ ${webdrivermanager.version}
test
@@ -330,7 +332,7 @@
true
none
- -Xdoclint:none
+ -Xdoclint:none
@@ -414,9 +416,8 @@
com.lazerycode.selenium
- driver-binary-downloader-maven-plugin
-
- 1.0.17
+ driver-binary-downloader-maven-plugin
+ ${driver-binary-downloader-maven-plugin.version}
true
@@ -563,7 +564,18 @@
24.2.6
11.0.12
true
+ 5.6.3
+ 1.0.18
+
+
+
+ org.seleniumhq.selenium
+ selenium-java
+ 4.17.0
+ test
+
+
diff --git a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java
index 48a3ee8..bd0dbc7 100644
--- a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java
+++ b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java
@@ -555,4 +555,12 @@ public static CheckboxColumn addCheckboxColumn(Grid grid,
public static void toggleSelectAllCheckbox(Grid grid, boolean visible) {
getHelper(grid).lazySelectAllGridHelper.toggleSelectAllCheckbox(visible);
}
+
+ private final GridRadioSelectionColumnHelper radioButtonSelectionColumnHelper =
+ new GridRadioSelectionColumnHelper<>(this);
+
+ public static GridRadioSelectionColumn showRadioSelectionColumn(Grid grid) {
+ return getHelper(grid).radioButtonSelectionColumnHelper.showRadioSelectionColumn();
+ }
+
}
diff --git a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumn.java b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumn.java
new file mode 100644
index 0000000..f98feb7
--- /dev/null
+++ b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumn.java
@@ -0,0 +1,58 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+package com.flowingcode.vaadin.addons.gridhelpers;
+
+import com.vaadin.flow.component.Component;
+import com.vaadin.flow.component.HasStyle;
+import com.vaadin.flow.component.Synchronize;
+import com.vaadin.flow.component.Tag;
+import com.vaadin.flow.component.dependency.JsModule;
+import com.vaadin.flow.component.dependency.NpmPackage;
+
+/**
+ * Server side implementation for the flow specific grid radio selection column.
+ */
+@Tag("grid-flow-radio-selection-column")
+@NpmPackage(value = "@vaadin/polymer-legacy-adapter", version = "24.3.2")
+@JsModule("@vaadin/polymer-legacy-adapter/style-modules.js")
+@JsModule("./fcGridHelper/grid-flow-radio-selection-column.js")
+public class GridRadioSelectionColumn extends Component implements HasStyle {
+
+ /**
+ * Sets this column's frozen state.
+ *
+ * @param frozen whether to freeze or unfreeze this column
+ */
+ public void setFrozen(boolean frozen) {
+ getElement().setProperty("frozen", frozen);
+ }
+
+ /**
+ * Gets the this column's frozen state.
+ *
+ * @return whether this column is frozen
+ */
+ @Synchronize("frozen-changed")
+ public boolean isFrozen() {
+ return getElement().getProperty("frozen", false);
+ }
+
+}
diff --git a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnHelper.java b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnHelper.java
new file mode 100644
index 0000000..590dc74
--- /dev/null
+++ b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnHelper.java
@@ -0,0 +1,62 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+package com.flowingcode.vaadin.addons.gridhelpers;
+
+import com.vaadin.flow.component.grid.Grid;
+import com.vaadin.flow.component.grid.Grid.SelectionMode;
+import java.io.Serializable;
+import lombok.RequiredArgsConstructor;
+
+@SuppressWarnings("serial")
+@RequiredArgsConstructor
+class GridRadioSelectionColumnHelper implements Serializable {
+
+ private final GridHelper helper;
+
+ private GridRadioSelectionColumn selectionColumn;
+
+ public GridRadioSelectionColumn showRadioSelectionColumn() {
+ remove();
+
+ Grid grid = helper.getGrid();
+ grid.setSelectionMode(SelectionMode.SINGLE);
+
+ selectionColumn = new GridRadioSelectionColumn();
+ selectionColumn.setClassName("fc-grid-radio-selection-column");
+
+ if (grid.getElement().getNode().isAttached()) {
+ grid.getElement().insertChild(0, selectionColumn.getElement());
+ } else {
+ grid.getElement().getNode().runWhenAttached(ui -> {
+ grid.getElement().insertChild(0, selectionColumn.getElement());
+ });
+ }
+
+ return selectionColumn;
+ }
+
+ private void remove() {
+ if (selectionColumn != null && selectionColumn.getElement().getNode().isAttached()) {
+ helper.getGrid().getElement().removeChild(selectionColumn.getElement());
+ }
+ }
+
+}
diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-flow-radio-selection-column.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-flow-radio-selection-column.js
new file mode 100644
index 0000000..9364114
--- /dev/null
+++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-flow-radio-selection-column.js
@@ -0,0 +1,131 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+import '@vaadin/grid/vaadin-grid-column.js';
+import { GridColumn } from '@vaadin/grid/src/vaadin-grid-column.js';
+import { GridRadioSelectionColumnBaseMixin } from './grid-radio-selection-column-base-mixin.js';
+
+class GridFlowRadioSelectionColumn extends GridRadioSelectionColumnBaseMixin(GridColumn) {
+
+ static get is() {
+ return 'grid-flow-radio-selection-column';
+ }
+
+ static get properties() {
+ return {
+ /**
+ * Override property to enable auto-width
+ */
+ autoWidth: {
+ type: Boolean,
+ value: true
+ },
+
+ /**
+ * Override property to set custom width
+ */
+ width: {
+ type: String,
+ value: '56px'
+ },
+
+ /**
+ * The previous state of activeItem. When activeItem turns to `null`,
+ * previousActiveItem will have an Object with just unselected activeItem
+ * @private
+ */
+ __previousActiveItem: Object,
+ };
+ }
+
+
+ constructor() {
+ super();
+ this.__boundOnActiveItemChanged = this.__onActiveItemChanged.bind(this);
+ }
+
+ /** @protected */
+ disconnectedCallback() {
+ this._grid.removeEventListener('active-item-changed', this.__boundOnActiveItemChanged);
+ super.disconnectedCallback();
+ }
+
+ /** @protected */
+ connectedCallback() {
+ super.connectedCallback();
+ if (this._grid) {
+ this._grid.addEventListener('active-item-changed', this.__boundOnActiveItemChanged);
+ }
+ }
+
+ /**
+ * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user
+ * selecting an item.
+ *
+ * @param {Object} item the item to select
+ * @protected
+ * @override
+ */
+ _selectItem(item) {
+ this._grid.$connector.doSelection([item], true);
+ }
+
+ /**
+ * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user
+ * deselecting an item.
+ *
+ * @param {Object} item the item to deselect
+ * @protected
+ * @override
+ */
+ _deselectItem(item) {
+ this._grid.$connector.doDeselection([item], true);
+ }
+
+
+ /** @private */
+ __onActiveItemChanged(e) {
+ const activeItem = e.detail.value;
+ if (activeItem) {
+ if(this.__previousActiveItem !== activeItem) {
+ this._deselectItem(this.__previousActiveItem);
+ }
+ this._selectItem(activeItem);
+ this.__previousActiveItem = activeItem;
+ } else {
+ this.__previousActiveItem = undefined;
+ }
+ }
+
+ /**
+ * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user clicked on an item.
+ *
+ * @param {Object} item the clicked item
+ * @protected
+ * @override
+ */
+ _onItemClicked(item) {
+ super._onItemClicked(item);
+ this.__previousActiveItem = item;
+ }
+
+}
+
+customElements.define(GridFlowRadioSelectionColumn.is, GridFlowRadioSelectionColumn);
diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-base-mixin.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-base-mixin.js
new file mode 100644
index 0000000..2318520
--- /dev/null
+++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-base-mixin.js
@@ -0,0 +1,116 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+import { addListener } from '@vaadin/component-base/src/gestures.js';
+
+/**
+ * A mixin that provides basic functionality for the
+ * ``. This includes properties, cell rendering,
+ * and overridable methods for handling changes to the selection state.
+ *
+ * **NOTE**: This mixin is re-used by the Flow component, and as such must not
+ * implement any selection state updates for the column element or the grid.
+ * Web component-specific selection state updates must be implemented in the
+ * `` itself, by overriding the protected methods
+ * provided by this mixin.
+ *
+ * @polymerMixin
+ */
+export const GridRadioSelectionColumnBaseMixin = (superClass) =>
+ class GriRadioSelectionColumnBaseMixin extends superClass {
+ static get properties() {
+ return {
+ /**
+ * Width of the cells for this column.
+ */
+ width: {
+ type: String,
+ value: '58px',
+ },
+
+ /**
+ * Flex grow ratio for the cell widths. When set to 0, cell width is fixed.
+ * @attr {number} flex-grow
+ * @type {number}
+ */
+ flexGrow: {
+ type: Number,
+ value: 0,
+ },
+
+ /**
+ * When true, the active gets automatically selected.
+ * @attr {boolean} auto-select
+ * @type {boolean}
+ */
+ autoSelect: {
+ type: Boolean,
+ value: false,
+ },
+
+ };
+ }
+
+ static get observers() {
+ return [
+ '_onHeaderRendererOrBindingChanged(path)',
+ ];
+ }
+
+ /**
+ * Renders the Select Row radio button to the body cell.
+ *
+ * @override
+ */
+ _defaultRenderer(root, _column, { item, selected }) {
+ let radioButton = root.firstElementChild;
+ if (!radioButton) {
+ radioButton = document.createElement('vaadin-radio-button');
+ radioButton.setAttribute('aria-label', 'Select Row');
+ root.appendChild(radioButton);
+ // Add listener after appending, so we can skip the initial change event
+ radioButton.addEventListener('checked-changed', this.__onSelectRowCheckedChanged.bind(this));
+ }
+
+ radioButton.__item = item;
+ radioButton.__rendererChecked = selected;
+ radioButton.checked = selected;
+ }
+
+ /**
+ * Selects the row when the Select Row radio button is clicked.
+ * The listener handles only user-fired events.
+ *
+ * @private
+ */
+ __onSelectRowCheckedChanged(e) {
+ // Skip if the state is changed by the renderer.
+ if (e.target.checked === e.target.__rendererChecked) {
+ return;
+ }
+
+ this._onItemClicked(e.target.__item);
+ }
+
+ _onItemClicked(item){
+ this._selectItem(item);
+ }
+
+ };
diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-mixin.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-mixin.js
new file mode 100644
index 0000000..f040074
--- /dev/null
+++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-mixin.js
@@ -0,0 +1,118 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+import { GridRadioSelectionColumnBaseMixin } from './grid-radio-selection-column-base-mixin.js';
+
+/**
+ * @polymerMixin
+ * @mixes GridSelectionColumnBaseMixin
+ */
+export const GridRadioSelectionColumnMixin = (superClass) =>
+ class extends GridRadioSelectionColumnBaseMixin(superClass) {
+ static get properties() {
+ return {
+ /**
+ * The previous state of activeItem. When activeItem turns to `null`,
+ * previousActiveItem will have an Object with just unselected activeItem
+ * @private
+ */
+ __previousActiveItem: Object,
+ };
+ }
+
+ constructor() {
+ super();
+
+ this.__boundOnActiveItemChanged = this.__onActiveItemChanged.bind(this);
+ this.__boundOnSelectedItemsChanged = this.__onSelectedItemsChanged.bind(this);
+ }
+
+ /** @protected */
+ disconnectedCallback() {
+ this._grid.removeEventListener('active-item-changed', this.__boundOnActiveItemChanged);
+ this._grid.removeEventListener('selected-items-changed', this.__boundOnSelectedItemsChanged);
+ super.disconnectedCallback();
+ }
+
+ /** @protected */
+ connectedCallback() {
+ super.connectedCallback();
+ if (this._grid) {
+ this._grid.addEventListener('active-item-changed', this.__boundOnActiveItemChanged);
+ this._grid.addEventListener('selected-items-changed', this.__boundOnSelectedItemsChanged);
+ }
+ }
+
+ /**
+ * Override a method from `GridSelectionColumnBaseMixin` to handle the user
+ * selecting an item.
+ *
+ * @param {Object} item the item to select
+ * @protected
+ * @override
+ */
+ _selectItem(item) {
+ this._grid.selectItem(item);
+ }
+
+ /**
+ * Override a method from `GridSelectionColumnBaseMixin` to handle the user
+ * deselecting an item.
+ *
+ * @param {Object} item the item to deselect
+ * @protected
+ * @override
+ */
+ _deselectItem(item) {
+ this._grid.deselectItem(item);
+ }
+
+ /** @private */
+ __onActiveItemChanged(e) {
+ const activeItem = e.detail.value;
+ this.__previousSelectionCleared = false;
+ if (this.autoSelect && activeItem) {
+ this._selectItem(activeItem);
+ this.__previousActiveItem = activeItem;
+ }
+ }
+
+ /** @private */
+ __onSelectedItemsChanged(e) {
+ if(!this.__previousSelectionCleared && this.__previousActiveItem){
+ this.__previousSelectionCleared = true;
+ this._deselectItem(this.__previousActiveItem);
+ }
+ }
+
+ /**
+ * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user clicked on an item.
+ *
+ * @param {Object} item the clicked item
+ * @protected
+ * @override
+ */
+ _onItemClicked(item) {
+ this.__previousSelectionCleared = false;
+ super._onItemClicked(item);
+ this.__previousActiveItem = item;
+ }
+
+ };
diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column.js
new file mode 100644
index 0000000..8c9f349
--- /dev/null
+++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column.js
@@ -0,0 +1,56 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+import '@vaadin/radio-group/vaadin-radio-button.js';
+import { defineCustomElement } from '@vaadin/component-base/src/define.js';
+import { GridColumn } from './vaadin-grid-column.js';
+import { GridRadioSelectionColumnMixin } from './grid-radio-selection-column-mixin.js';
+
+/**
+ * `` is a helper element for the ``
+ * that provides default renderers and functionality for item selection.
+ *
+ * #### Example:
+ * ```html
+ *
+ *
+ *
+ *
+ * ...
+ * ```
+ *
+ * By default the selection column displays `` elements in the
+ * column cells. The radio button in the body rows toggle selection of the corresponding row item.
+ *
+ * __The default content can also be overridden__
+ *
+ * @customElement
+ * @extends GridColumn
+ * @mixes GridSelectionColumnMixin
+ */
+class GridRadioSelectionColumn extends GridRadioSelectionColumnMixin(GridColumn) {
+ static get is() {
+ return 'grid-radio-selection-column';
+ }
+}
+
+defineCustomElement(GridRadioSelectionColumn);
+
+export { GridRadioSelectionColumn };
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java
index d230a1b..4eea42e 100644
--- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java
@@ -52,5 +52,6 @@ public GridHelpersDemoView() {
addDemo(CheckboxColumnDemo.class);
addDemo(EmptyGridLabelDemo.class);
addDemo(HeightByRowsDemo.class);
+ addDemo(GridRadioSelectionColumnDemo.class);
}
}
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnDemo.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnDemo.java
new file mode 100644
index 0000000..a4bec82
--- /dev/null
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnDemo.java
@@ -0,0 +1,65 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+package com.flowingcode.vaadin.addons.gridhelpers;
+
+import com.flowingcode.vaadin.addons.demo.DemoSource;
+import com.vaadin.flow.component.grid.Grid;
+import com.vaadin.flow.component.grid.GridSingleSelectionModel;
+import com.vaadin.flow.component.html.Div;
+import com.vaadin.flow.component.orderedlayout.VerticalLayout;
+import com.vaadin.flow.data.provider.DataProvider;
+import com.vaadin.flow.router.PageTitle;
+import com.vaadin.flow.router.Route;
+
+@PageTitle("Radio Selection Column")
+@DemoSource
+@Route(value = "grid-helpers/radio-selection-column", layout = GridHelpersDemoView.class)
+public class GridRadioSelectionColumnDemo extends VerticalLayout {
+
+ Div selection = new Div();
+
+ public GridRadioSelectionColumnDemo() {
+ setSizeFull();
+
+ Grid grid = new Grid<>();
+ LazyTestData data = new LazyTestData();
+ grid.setItems(DataProvider.fromCallbacks(
+ query -> data.filter(query.getOffset(), query.getPageSize()), query -> data.count()));
+
+ grid.addColumn(Person::getFirstName).setHeader("First name");
+ grid.addColumn(Person::getLastName).setHeader("Last name");
+ grid.addColumn(Person::getPhoneNumber).setHeader("Phone");
+
+ GridHelper.showRadioSelectionColumn(grid).setFrozen(true);
+
+ grid.setSizeFull();
+ ((GridSingleSelectionModel) grid.getSelectionModel()).setDeselectAllowed(false);
+ grid.asSingleSelect().addValueChangeListener(e -> {
+ if (e.getValue() != null) {
+ selection.setText(
+ "Selected row: " + e.getValue().getFirstName() + " " + e.getValue().getLastName());
+ }
+ });
+
+ add(grid, selection);
+ }
+
+}
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java
index d513be0..e29043e 100644
--- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java
@@ -85,6 +85,14 @@ public TestBenchElement getSelectionCheckbox(int rowIndex) {
return (TestBenchElement) elements.stream().findFirst().orElse(null);
}
+ public TestBenchElement getSelectionRadioButton(int rowIndex) {
+ // assumes that Grid is in single-selection mode
+ TestBenchElement cell = getSlottedCell(getRow(rowIndex));
+ List elements = cell.findElements(By.tagName("vaadin-radio-button"));
+ return (TestBenchElement) elements.stream().findFirst().orElse(null);
+ }
+
+
private TestBenchElement getSlottedCell(WebElement e) {
String slot = e.findElement(By.tagName("slot")).getAttribute("name");
return findElement(By.cssSelector(String.format("[slot='%s']", slot)));
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridRadioSelectionColumnIT.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridRadioSelectionColumnIT.java
new file mode 100644
index 0000000..65a8842
--- /dev/null
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridRadioSelectionColumnIT.java
@@ -0,0 +1,134 @@
+/*-
+ * #%L
+ * Grid Helpers Add-on
+ * %%
+ * Copyright (C) 2022 - 2024 Flowing Code
+ * %%
+ * 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.
+ * #L%
+ */
+
+package com.flowingcode.vaadin.addons.gridhelpers.it;
+
+import static java.time.temporal.ChronoUnit.SECONDS;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.empty;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import com.flowingcode.vaadin.testbench.rpc.HasRpcSupport;
+import com.vaadin.flow.component.grid.testbench.GridElement;
+import com.vaadin.testbench.TestBenchElement;
+import java.time.Duration;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+public class GridRadioSelectionColumnIT extends AbstractViewTest implements HasRpcSupport {
+
+ IntegrationViewCallables $server = createCallableProxy(IntegrationViewCallables.class);
+ GridHelperElement grid;
+
+ public GridRadioSelectionColumnIT() {
+ super("it");
+ }
+
+ @Override
+ public void setup() throws Exception {
+ super.setup();
+ grid = new GridHelperElement($(GridElement.class).waitForFirst());
+ }
+
+ @Test
+ public void testRadioSelectionColumnShown() {
+ // assert that the first column is not the one with radio button
+ assertNull("the first column has radio buttons", grid.getSelectionRadioButton(0));
+
+ $server.showRadioSelectionColumn();
+
+ waitUntil(ExpectedConditions
+ .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column")));
+
+ // assert that the first column is the one with radio buttons
+ assertNotNull("the first column has not any radio buttons", grid.getSelectionRadioButton(0));
+ }
+
+ @Test
+ public void testShouldSelectRowOnClick() {
+ $server.showRadioSelectionColumn();
+
+ waitUntil(ExpectedConditions
+ .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column")));
+
+ assertThat($server.getSelectedRows(), empty());
+
+ grid.getCell(0, 1).click();
+ assertThat($server.getSelectedRows(), contains(0));
+
+ grid.getCell(4, 1).click();
+ assertThat($server.getSelectedRows(), contains(4));
+ }
+
+ @Test
+ public void testShouldSelectRowOnRadioButtonClick() {
+ $server.showRadioSelectionColumn();
+
+ waitUntil(ExpectedConditions
+ .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column")));
+
+
+ assertThat($server.getSelectedRows(), empty());
+
+ TestBenchElement radioButton = grid.getSelectionRadioButton(0);
+ radioButton.click();
+ assertThat($server.getSelectedRows(), contains(0));
+
+
+ radioButton = grid.getSelectionRadioButton(4);
+ radioButton.click();
+ assertThat($server.getSelectedRows(), contains(4));
+ }
+
+ @Test
+ public void testRadioSelectionColumnFrozen() {
+ $server.showRadioSelectionColumn();
+
+ waitUntil(ExpectedConditions
+ .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column")));
+
+ TestBenchElement selectionColElement = grid.$("grid-flow-radio-selection-column").first();
+
+ String frozen = "return arguments[0].frozen";
+
+
+ new WebDriverWait(getDriver(), Duration.of(2, SECONDS))
+ .until(ExpectedConditions.attributeContains(selectionColElement, "frozen", "false"));
+
+ // assert that the selection column is not frozen by default
+ assertFalse("Selection column is frozen", (Boolean) executeScript(frozen, selectionColElement));
+
+ // make selection column frozen
+ selectionColElement.setProperty("frozen", true);
+
+ new WebDriverWait(getDriver(), Duration.of(2, SECONDS))
+ .until(ExpectedConditions.attributeContains(selectionColElement, "frozen", "true"));
+
+ // assert that the selection column is now frozen
+ assertTrue("Selection column is not frozen",
+ (Boolean) executeScript(frozen, selectionColElement));
+ }
+
+}
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java
index 28f8b85..e677455 100644
--- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java
@@ -20,6 +20,7 @@
package com.flowingcode.vaadin.addons.gridhelpers.it;
import com.flowingcode.vaadin.addons.gridhelpers.GridHelper;
+import com.flowingcode.vaadin.addons.gridhelpers.GridRadioSelectionColumn;
import com.flowingcode.vaadin.addons.gridhelpers.Person;
import com.flowingcode.vaadin.addons.gridhelpers.TestData;
import com.flowingcode.vaadin.testbench.rpc.JsonArrayList;
@@ -178,4 +179,9 @@ public void setHeaderVisible(boolean visible) {
public void setFooterVisible(boolean visible) {
grid.setFooterVisible(visible);
}
+
+ @Override
+ public void showRadioSelectionColumn() {
+ grid.showRadioSelectionColumn();
+ }
}
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java
index 0a938b1..ee8590c 100644
--- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java
@@ -59,4 +59,5 @@ public interface IntegrationViewCallables extends RmiCallable {
void setFooterVisible(boolean visible);
+ void showRadioSelectionColumn();
}
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java
index 5a617d2..9dc31cc 100644
--- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import com.flowingcode.vaadin.addons.gridhelpers.GridHelper;
@@ -190,4 +191,9 @@ public void testMenuToggleColumn() {
assertTrue(GridHelper.isMenuToggleColumn(toggleColumn));
}
+ @Test
+ public void testShowRadioSelectionColumn() {
+ assertNotNull(grid.showRadioSelectionColumn());
+ }
+
}
diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java
index c4f76d6..e765697 100644
--- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java
+++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java
@@ -48,6 +48,7 @@ public void testSerialization() throws ClassNotFoundException, IOException {
try {
Grid> grid = new Grid<>();
GridHelper.setColumnToggleVisible(grid, false);
+ GridHelper.showRadioSelectionColumn(grid);
testSerializationOf(grid);
} catch (Exception e) {
Assert.fail("Problem while testing serialization: " + e.getMessage());