sk_dev
sk_dev

Reputation: 315

Vaadin Grid (Multiselect): restore selection after refresh

A Vaadin grid shows data which is constantly updated by a background process. A user might select one or more rows to carry out various functions. The user might refresh the data from the backend (which updates rows shown in the grid).

The application needs to restore the selected items after a grid refresh. grid.getSelectedItems() has to return the current instance of the selected items.

Refresh is implemented as follows:

void refresh() {
    final var beanSet = grid.getSelectedItems();
    dataProvider.refreshAll();             // refresh from backend
    grid.asMultiSelect().select(beanSet);  // restore previously selected items
}

Updating the grid works fine, but the selection is only partly restored: the "selected" checkbox is checked for the items in beanSet but querying grid.getSelectedItems() still returns the old instances.

Reproducer: https://github.com/skiedrowski/vaadin-grid-restore-selection, package com.example.application.views.idstyle -> check the notification after clicking "Update selected".

What is the correct way to update the selected items?

Context:

Upvotes: 2

Views: 804

Answers (2)

Roman Kovařík
Roman Kovařík

Reputation: 81

This is how we solve this in our application:

A]

  • fresh items are retrieved lazily
  • the only time when refreshed selection is needed is when we want to operate with the selected items (such as edit or another action, otherwise obsolete selected items don't matter)
  • the backend is able to return fresh item by ID
  • there is no need to update the selection on fetch() (which could introduce inconsistencies if a part of the selection is already updated but the rest haven't been fetched yet)

B]

  • we have some data providers which just hold wrappers for actual items
  • so any interaction with the items fetches fresh data under the hood
  • for the record, this was not done to solve this problem but mitigates it as a sideeffect

Upvotes: 0

ollitietavainen
ollitietavainen

Reputation: 4275

I believe the problem in your sample project is that you're always recycling a set of selected objects which contain the "old" data. You read out a reference to the old items in var beanSet = grid.getSelectedItems(); and store them back into the selection with grid.asMultiSelect().select(beanSet);

A lazy-loading Grid can't know if the programmatically set selection is a collection of objects that are available in the backend - it would need to fetch the entire backing dataset to do that. So when the selection is updated from the server, it could be any objects of the correct type, whether they actually exist in the data set or not.

What could do yourself is pass the selection set to the backend, update the items and then pass them back to the Grid's selection.

An open question that remains is whether Grid should update the selection when a fetch returns items that are equal to items in the selection. I can't immediately tell if that is a) possible, or b) a sensible thing to do

Upvotes: 2

Related Questions