In a Vaadin 23.3.10 Grid I'd like to select a row that is next to a row that was selected before. Therefore I read the items from the DataCommunicator. Most cases work fine, but the DataCommunicator seems to be not in sync with the DataProvider after calling dataProvider.remove(x)
and dataProvider.refreshAll()
.
The button is plugin-based so the code snippet that selects the next row doesn't know whether some other plugin that ran before removed an item from the grid.
Here is a code example that only shows that a DataProvider and a DataCommunicator are out of sync after removing an item from the DataProvider and that the DataCommunicator is not consistent in its own:
@Route("sandbox")
public class SandboxView extends VerticalLayout {
private class Item {
String name;
private Item(String name) {this.name=name;}
}
public SandboxView() {
// Generate some items
Item a = new Item("a");
Item b = new Item("b");
Item c = new Item("c");
List<Item> items = new ArrayList<>();
items.add(a);
items.add(b);
items.add(c);
ListDataProvider<Item> dataProvider = new ListDataProvider<>(items);
// Create a grid
Grid<Item> grid = new Grid<>();
grid.setItems(dataProvider);
grid.addColumn(item -> item.name).setHeader("Name");
this.add(grid);
// Create a button that removes an item from the grid
Button button = new Button("Remove item A");
button.addClickListener(event -> {
DataCommunicator<Item> dataCommunicator = grid.getDataCommunicator();
printDataCommunicatorItemInfo(dataCommunicator);
// Output is as expected:
// 3 items
// Item: a
// Item: b
// Item: c
dataProvider.getItems().remove(a);
printDataCommunicatorItemInfo(dataCommunicator);
// Output is still the same:
// 3 items
// Item: a
// Item: b
// Item: c
dataProvider.refreshAll();
printDataCommunicatorItemInfo(dataCommunicator);
// ## UNEXPECTED ##
// Output is out of sync:
// 2 items
// Item: a
// Item: b
}
);
this.add(button);
}
private void printDataCommunicatorItemInfo(DataCommunicator<Item> dataCommunicator) {
System.out.println(dataCommunicator.getItemCount()+" items");
for (int i=0;i<dataCommunicator.getItemCount();i++) {
System.out.println("Item: "+dataCommunicator.getItem(i).name);
}
}
}
The problem is that dataCommunicator.getItemCount()
returns the reduced number of items (2) but dataCommunicator.getItem(...)
still returns the removed item (a).
Question: How can I force the dataCommunicator to get in sync again?
In Vaadin 23, you can get the next item from the GridListDataView.
For example:
GridListDataView<Person> dataView = grid.setItems(DataProvider.ofCollection(PersonUtil.buildPersons()));
Person item; // item a
Optional<Person> nextItem = dataView.getNextItem(item); dataView.removeItem(item);
I'm not really sure about the dataCommunicator issue. I didn't look into the issue in details but you don't need to use it.