Guttorm
(Guttorm Vik)
March 19, 2026, 4:44pm
1
I have a Combobox replacement consisting of a CompositeField with a TextField and a Popover panel with a SelectionGrid.
When I use this in a form, it works great.
When I use it in an editable SelectionGrid, I get weird behavior and possibly an exception.
When I click on row X in the SelectionGrid in the Popover panel, it also tries to set the selection to row X in the outer SelectionGrid. That causes the selection to jump around or throw an IndexOutOfBoundsException.
Switching both back to regular Grid solves the issue (but then I get back the other issues that SelectionGrid solved for me)
I assume this is an issue with SelectionGrid, so I’ve registered a bug, but while waiting for a fix, can anyone think of a possible workaround?
The only thing I can think of just now is to use regular Grid in the Combobox replacement, and only use SelectionGrid for the main, editable Grid.
opened 04:35PM - 19 Mar 26 UTC
I have a Combobox replacement consisting of a CompositeField with a TextField an… d a Popover panel with a SelectionGrid.
When I use this in a form, it works great.
When I use it in an editable SelectionGrid, I get weird behavior and possibly an exception.
When I click on row X in the SelectionGrid in the Popover panel, it also tries to set the selection to row X in the outer SelectionGrid. That causes the selection to jump around or throw an IndexOutOfBoundsException.
Switching both back to regular Grid solves the issue (but then I get back the other issues that SelectionGrid solved for me)
This is with Vaadin 25.0.7 and SelectionGrid 4.0.1
Not sure the IndexOutOfBoundsException stacktrace helps, since I assume it is too late to see why it tried to set that selection.
Here I have clicked on row 5 in the "Combobox", and it is trying to set that as selection in the outer SelectionGrid, which only has 1 row:
```
17:25:20,842 ERROR [com.ptsmc.vaadin.CustomErrorHandler] (default task-4) IndexOutOfBoundsException: java.lang.IndexOutOfBoundsException: Given index 4 is outside of the accepted range '0 - 0'
at deployment.ptsmc.ear//com.vaadin.flow.data.provider.DataCommunicator.getItem(DataCommunicator.java:636)
at deployment.ptsmc.ear//com.vaadin.componentfactory.selectiongrid.SelectionGrid.obtainNewSelectedItems(SelectionGrid.java:189)
at deployment.ptsmc.ear//com.vaadin.componentfactory.selectiongrid.SelectionGrid.lambda$selectRangeOnly$2bc3653f$1(SelectionGrid.java:240)
at deployment.ptsmc.ear//com.vaadin.flow.internal.StateTree.lambda$runExecutionsBeforeClientResponse$2(StateTree.java:398)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at deployment.ptsmc.ear//com.vaadin.flow.internal.StateTree.runExecutionsBeforeClientResponse(StateTree.java:393)
at deployment.ptsmc.ear//com.vaadin.flow.server.communication.UidlWriter.encodeChanges(UidlWriter.java:386)
at deployment.ptsmc.ear//com.vaadin.flow.server.communication.UidlWriter.createUidl(UidlWriter.java:152)
at deployment.ptsmc.ear//com.vaadin.flow.server.communication.UidlRequestHandler.createUidl(UidlRequestHandler.java:184)
at deployment.ptsmc.ear//com.vaadin.flow.server.communication.UidlRequestHandler.writeUidl(UidlRequestHandler.java:173)
at deployment.ptsmc.ear//com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:136)
at deployment.ptsmc.ear//com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:63)
at deployment.ptsmc.ear//com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1839)
at deployment.ptsmc.ear//com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:402)
at jakarta.servlet.api@6.0.0//jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
```
Guttorm
(Guttorm Vik)
March 20, 2026, 10:25am
2
I’ve now tried using SelectionGrid for the outer grid, and regular Grid in my Combobox replacement in the editor → Same error.
Looks like the outer SelectionGrid listens on any event that happens inside it?
Guttorm
(Guttorm Vik)
March 23, 2026, 9:55am
3
Trying to wrap my head around the code.
Shouldn’t this onClick handler have an e.stopPropagation()?:
* 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%
*/
customElements.whenDefined("vaadin-selection-grid").then(() => {
const Grid = customElements.get("vaadin-selection-grid");
if (Grid) {
const oldClickHandler = Grid.prototype._onClick;
Grid.prototype._onClick = function _click(e) {
const boundOldClickHandler = oldClickHandler.bind(this);
boundOldClickHandler(e);
this._selectionGridSelectRow(e);
};
Grid.prototype.old_onNavigationKeyDown = Grid.prototype._onNavigationKeyDown;
Grid.prototype._onNavigationKeyDown = function _onNavigationKeyDownOverridden(e, key) {
this.old_onNavigationKeyDown(e,key);
const ctrlKey = (e.metaKey)?e.metaKey:e.ctrlKey;
if (e.shiftKey || !ctrlKey) {
Did a small experiment in the browser DevTools:
const n = customElements.get("vaadin-selection-grid");const i=n.prototype._onClick;n.prototype._onClick=function(e){i.bind(this)(e),this._selectionGridSelectRow(e);e.stopPropagation()}
That seems to solve it, though I have no idea if I’m maybe breaking something else
Guttorm
(Guttorm Vik)
March 23, 2026, 10:16am
4
Would this be a sensible way to apply this hack until it gets fixed?
public MainLayout() {
// fix bug in SelectionGrid
UI ui = UI.getCurrent();
boolean loaded = ui.getElement().getProperty("selection-grid-fix-applied", false);
if(!loaded) {
ui.getPage().executeJs("const n = customElements.get(\"vaadin-selection-grid\");const i=n.prototype._onClick;n.prototype._onClick=function(e){i.bind(this)(e),this._selectionGridSelectRow(e);e.stopPropagation()}");
ui.getElement().setProperty("selection-grid-fix-applied", true);
}
Guttorm
(Guttorm Vik)
March 23, 2026, 3:36pm
5
Sigh, wasn’t that easy… By calling stopPropagation several other things broke;
Context menu no longer closes on click outside
In the variant of my Combobox replacement, where I support multiselect, it is no longer possible to untick a selection; It gets instantly reselected
As soon as I commented out my hack, these two started to work as expected again