Hello, I have question about how to check selectAll checkbox in vaadin 14 grid component what is in multiselect mode? I need to select all items in grid programatically but it seems that it’s not possible or not complete. I can select all items in multiselect grid but selectAll checkbox in grid’s header is not selected. I was not able to find any proper method to select this checkbox. I’m using HierarchicalDataProvider.
java.lang.IllegalArgumentException: Hierarchical data provider doesn’t support non-hierarchical queries
at com.vaadin.flow.data.provider.hierarchy.HierarchicalDataProvider.fetch(HierarchicalDataProvider.java:80)
at com.vaadin.flow.component.grid.AbstractGridMultiSelectionModel.selectAll(AbstractGridMultiSelectionModel.java:189)
Right, looks like that’s not doable in a HierarchicalDataProvider then. You’d need to access the private final GridSelectionColumn selectionColumn; in AbstractGridMultiSelectionModel to call selectionColumn.setSelectAllCheckboxState(true);, but it’s a private variable with no accessors. You could technically use Reflection to hack it: https://www.javatpoint.com/how-to-call-private-method-from-another-class-in-java
OK thanks for suggenstion and maybe it can works but it should be fixed in some next vaadin version.
I have also found another problem with selectAll. When I select all items/rows on grid manually, selectAll checkbox is not automatically checked/select.
I’ve tried to implement it through reflection but I ran into problem with method what is called on select by client:
AbstractGridMultiSelectionModel.class
...
public void selectFromClient(T item) {
if (isSelected(item)) {
return;
}
Set<T> oldSelection = new LinkedHashSet<>(selected);
boolean added = selected.add(item);
if (added) {
fireSelectionEvent(new MultiSelectionEvent<>(getGrid(),
getGrid().asMultiSelect(), oldSelection, true));
long size = 0;
final DataProvider<T, ?> dataProvider = getGrid()
.getDataCommunicator().getDataProvider();
// Avoid throwing an IllegalArgumentException in case of
// HierarchicalDataProvider
if (!(dataProvider instanceof HierarchicalDataProvider)) {
size = dataProvider.size(new Query<>());
}
selectionColumn.setSelectAllCheckboxState(size == selected.size());
}
}
...
This method fire event (fireSelectionEvent) from which I can handle selectAll checkbox through reflection. Problem is that after this event handling it calls setSelectAllCheckboxState again and set it always to false for HierarchicalDataProvider. So I’m unable to set selectAll checkbox to true and also I don’t know how to override this behaviour.
Can you change this method and call selectionColumn.setSelectAllCheckboxState(size == selected.size()); BEFORE fireSelectionEvent? Otherwise I’m not able to implement it. Maybe only with help by some ASM or CGLIB but I think that is not good idea.
It seems that solution is to make own implementation of AbstractGridMultiSelectionModel and use it in TreeGrid instance with usage of reflection on both parts. But it isn’t good solution for long time, please fix it.