Java – Update components from the Vaadin event listener

Update components from the Vaadin event listener… here is a solution to the problem.

Update components from the Vaadin event listener

I would like to know how to update components in Vaadin when changing data from event listeners. The code in question looks like this:

Set<Long> identifiers = new LinkedHashSet<>();

Grid<Long> grid = new Grid<>(Long.class);
grid.addColumn((ValueProvider<Long, Long>) value -> value);
grid.setDataProvider(new ListDataProvider<>(identifiers));

TextField identifier = new TextField();
identifier.getElement().addEventListener("keyup", event -> {
  String value = event.getEventData().getString("element.value");
  if (value != null && value.length() > 0) {
    try {
      identifiers.add(Long.parseLong(value));
      identifier.clear();
    } catch (NumberFormatException e) {
      Notification.show("Not a valid identifier: " + value);
    }
  }
}).addEventData("element.value").setFilter("event.key == 'Enter'");

Events are dispatched as I expect, but the grid is not re-rendered in the user View. How do I tell the Vaadin grid that it needs to be re-rendered from the event handler?

Solution

Re-rendering the mesh is done by refreshing the DataProvider. You can do this:

grid.getDataProvider().refreshAll();

EDIT: My explanation is based on false assumptions

ListDataProvider does not copy the collection provided to it, so changing the original item collection affects the data provider. But it doesn’t automatically re-render itself, you still have to call refreshAll().

refreshAll() basically duplicates the data provider item, rebuilds the row, and reapplies any custom column definitions (i.e. style builders and other state-based decisions). As long as you keep the original collection in sync with what you want to display, calling refreshAll() should work.

If you want to completely change the displayed list of items, you can either remove all items from the original collection (identifiers) and add new items to it, then refresh all, or you can simply set up a new data provider with the new item collection.
(This line also solves the problem with OP, but should be avoided if refreshAll is sufficient.) )

grid.setDataProvider(new ListDataProvider<>(otherIdentifiers));

Related Problems and Solutions