网格由数据提供者填充:如何在刷新后触发操作?

时间:2018-01-11 14:59:03

标签: vaadin vaadin8 vaadin-grid

在Vaadin 8.2中,我使用数据提供程序(AbstractBackEndDataProvider)将一个Grid绑定到bean。从数据库中提取数据,应用过滤器:

Grid grid = new Grid<>();
grid.setDataProvider(dataProvider.withConfigurableFilter()); // dataProvider derives from AbstractBackEndDataProvider<T,F>

基本流程如下:用户在表单中输入项目ID并提交,提交事件监听器获取用户输入,创建新过滤器并更新数据提供者:

filterSubmitButton.addClickListener(event -> {
    try {
        ItemListFilter filter = new ItemListFilter(
            itemFilter.getValue(), // itemFilter = new TextField();
        );
        filterBinder.writeBean(filter);
        dataProvider.setFilter(filter);
    } catch (ValidationException e) {
        //...
    }
 });

当数据提供者更新过滤器时,它会调用一个服务来从DB中获取新项目并应用过滤器(到数据库查询)。 Vaadin后来负责用新数据刷新网格。

我想要的是在最后一刻进行回调。假设一个用例是检查过滤的获取结果集是否只包含一个项目,以选择Grid中的这个项目(反过来它将触发一个事件,在另一个窗格中显示项目详细信息)。或者在加载初始列表后选择第一个网格行

但问题是既没有grid.addRefreshListener()也没有dataProvider.addRefreshmentListener()。在这种情况下,任何其他听众似乎都不适用。

感谢您提前提供任何帮助。

2 个答案:

答案 0 :(得分:0)

我发现的唯一解决方案是权衡。

项目列表演示者(使用网格处理视图)将其com.vaadin.event.EventRouter传递给dataProvider(我已修改dataProvider以将EventRounter作为成员保存)。而现在,不是直接从dataProvider流式传输数据结果,而是触发数据被提取的事件(使用EventRouter)。演示者可以订阅此事件,然后将其委托给详细信息面板的演示者。在那里你可以阅读获取的结果(事件包含它们),检查是否只有一个条目并通过id打开它。

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的事件)。 / LI>
  2. 这是一种肮脏的技巧,因为现在dataProvider会抛出事件并与eventRouters个观看者/演示者交易。另一方面,Vaadins数据提供者无论如何都允许订阅事件。使用那个开箱即用的grid-dataProvider反应绑定,我们只是在获取数据后没有触发事件,因此我们以自定义方式执行此操作。
  3. 还可以使用给定的Vaadin订阅者dataProvider.addDataProviderListener,并从那里委托包含填充过滤器的事件,并在详细信息面板中独立捕捉该事件。但是,你需要执行两次sql查询(这可能是昂贵的)或缓存它们等。与给定的相比没有任何好处,仍然是一个权衡。

答案 1 :(得分:0)

调用dataprovider.refreshAll()时,将自动刷新关联的网格。因此,在代码中的以下几行之后:

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

添加逻辑以获取返回记录的大小(例如dataprovider.size()),如果该值等于一个(01),则调用其他逻辑以选择一个记录并在另一面板中显示其详细信息。