Сетка, заполненная поставщиком данных: как вызвать действие после обновления?
В Vaadin 8.2 у меня есть Grid, привязанная к бину с использованием поставщика данных (AbstractBackEndDataProvider). Данные извлекаются из БД, применяются фильтры:
Grid grid = new Grid<>();
grid.setDataProvider(dataProvider.withConfigurableFilter()); // dataProvider derives from AbstractBackEndDataProvider<T,F>
Существенный процесс заключается в следующем: пользователь вводит идентификатор элемента в форму и отправляет, слушатель события submit получает пользовательский ввод, создает новый фильтр и обновляет поставщика данных:
filterSubmitButton.addClickListener(event -> {
try {
ItemListFilter filter = new ItemListFilter(
itemFilter.getValue(), // itemFilter = new TextField();
);
filterBinder.writeBean(filter);
dataProvider.setFilter(filter);
} catch (ValidationException e) {
//...
}
});
Когда поставщик данных обновляет фильтр, он вызывает службу для извлечения новых элементов из БД с применением фильтра (к запросу БД). Vaadin позаботится об обновлении Grid новыми данными после этого.
То, что я хочу - это перезвонить в этот последний момент. Скажем, сценарий использования будет состоять в том, чтобы проверить, содержит ли отфильтрованный выбранный результирующий набор только один элемент, чтобы выбрать этот элемент в таблице (что, в свою очередь, вызовет событие, отображающее детали элемента в другой панели). Или выбрать первую строку сетки после загрузки исходного списка
Но проблема в том, что нет ни grid.addRefreshListener(), ни dataProvider.addRefreshmentListener(). Любые другие слушатели, кажется, не применяются в этом случае.
Спасибо за любую помощь заранее.
1 ответ
Единственное решение, которое я нашел, - это компромисс.
Ведущий списка элементов (который обрабатывает представление с сеткой) передает его com.vaadin.event.EventRouter
в dataProvider
(Я изменил dataProvider
провести EventRounter в качестве члена). И теперь вместо потоковой БД результаты прямо из dataProvider
Я запускаю событие, когда данные извлекаются (используя EventRouter). Докладчик может подписаться на это событие, а затем делегировать его докладчику на панели сведений. Там вы можете прочитать полученные результаты (событие содержит их), проверить, есть ли только одна запись, и открыть ее по идентификатору.
public class ListItemDataProvider extends AbstractBackEndDataProvider<Item, ItemFilter> {
//...
@Override
protected Stream<Item> fetchFromBackEnd(Query<Item, ItemFilter> query) {
// ...
List<Item> fetchedResults = service.fetch(query.getOffset(), query.getLimit(), orderBy, getFilter(query));
eventRouter.fireEvent(new FilteredDataFetchedEvent(this, fetchedResults));
return fetchedResults.stream();
}
}
@Controller
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ItemListPresenter {
// ...
public void addFilteredDataFetchedListener(ItemListView.FilteredDataFetchedListener listener) {
eventRouter.addListener(FilteredDataFetchedEvent.class, listener, FilteredDataFetchedListener.FILTERED_DATA_FETCHED);
}
}
Несколько заметок:
- Это не совсем то, что мне было нужно. Да, я могу использовать большую часть своего сценария использования, если фильтр применен, список перезагружается, и в представлении сведений также появляется событие для перезагрузки. Но я не могу повторно использовать прослушиватели событий selectionChanged для этого и на самом деле вообще не могу выбрать строку в сетке (только потому, что событие из
dataProdiver
бросается до обновления сетки). - Это своего рода подвох, потому что теперь
dataProvider
бросает события и имеет дело сeventRouters
просмотров / докладчиков. С другой стороны, поставщики данных Vaadins в любом случае разрешают подписываться на события. Используя это встроенное реактивное связывание grid-dataProvider, мы просто не генерируем событие после получения данных, поэтому мы делаем это нестандартным способом. - То, что также может работать, это использовать данного абонента Ваадина
dataProvider.addDataProviderListener
и делегировать оттуда событие, содержащее заполненный фильтр, и просто действовать независимо, перехватывая это событие на панели сведений. Но тогда вам нужно будет выполнить sql запросы дважды (что может быть дорогостоящим) или кэшировать их и т. Д. Это не дает никаких преимуществ по сравнению с заданным и все еще является компромиссом.
Когда вы вызываете dataprovider.refreshAll(), связанная сетка автоматически обновляется. Следовательно, после следующих строк в вашем коде:
filterBinder.writeBean(filter);
dataProvider.setFilter(filter);
добавить логику для получения размера возвращаемых записей (например, dataprovider.size ()) и, если он равен единице (01), вызвать другую логику, чтобы выбрать одну запись и отобразить ее детали на другой панели.