Сетка, заполненная поставщиком данных: как вызвать действие после обновления?

В 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);
    }
}

Несколько заметок:

  1. Это не совсем то, что мне было нужно. Да, я могу использовать большую часть своего сценария использования, если фильтр применен, список перезагружается, и в представлении сведений также появляется событие для перезагрузки. Но я не могу повторно использовать прослушиватели событий selectionChanged для этого и на самом деле вообще не могу выбрать строку в сетке (только потому, что событие из dataProdiver бросается до обновления сетки).
  2. Это своего рода подвох, потому что теперь dataProvider бросает события и имеет дело с eventRouters просмотров / докладчиков. С другой стороны, поставщики данных Vaadins в любом случае разрешают подписываться на события. Используя это встроенное реактивное связывание grid-dataProvider, мы просто не генерируем событие после получения данных, поэтому мы делаем это нестандартным способом.
  3. То, что также может работать, это использовать данного абонента Ваадина dataProvider.addDataProviderListener и делегировать оттуда событие, содержащее заполненный фильтр, и просто действовать независимо, перехватывая это событие на панели сведений. Но тогда вам нужно будет выполнить sql запросы дважды (что может быть дорогостоящим) или кэшировать их и т. Д. Это не дает никаких преимуществ по сравнению с заданным и все еще является компромиссом.

Когда вы вызываете dataprovider.refreshAll(), связанная сетка автоматически обновляется. Следовательно, после следующих строк в вашем коде:

filterBinder.writeBean(filter);
dataProvider.setFilter(filter);

добавить логику для получения размера возвращаемых записей (например, dataprovider.size ()) и, если он равен единице (01), вызвать другую логику, чтобы выбрать одну запись и отобразить ее детали на другой панели.

Другие вопросы по тегам