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

Vaadin 数据提供者填充的网格:刷新后如何触发操作?,vaadin,vaadin8,vaadin-grid,Vaadin,Vaadin8,Vaadin Grid,在Vaadin8.2中,我使用数据提供程序(AbstractBackEndDataProvider)将一个网格绑定到一个bean。从数据库中提取数据,应用过滤器: Grid grid = new Grid<>(); grid.setDataProvider(dataProvider.withConfigurableFilter()); // dataProvider derives from AbstractBackEndDataProvider<T,F> 当数据提供程

在Vaadin8.2中,我使用数据提供程序(AbstractBackEndDataProvider)将一个网格绑定到一个bean。从数据库中提取数据,应用过滤器:

Grid grid = new Grid<>();
grid.setDataProvider(dataProvider.withConfigurableFilter()); // dataProvider derives from AbstractBackEndDataProvider<T,F>
当数据提供程序更新了过滤器时,它调用一个服务从数据库中获取新项目,并应用过滤器(到数据库查询)。Vaadin负责随后用新数据刷新网格

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

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


感谢您提前提供的帮助。

我找到的唯一解决方案是权衡

item list presenter(用网格处理视图)将其
com.vaadin.event.EventRouter
传递给
dataProvider
(我修改了
dataProvider
,将EventRouter作为成员保存)。现在,我不再直接从
数据提供者
发送流式数据库结果,而是触发一个获取数据的事件(使用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);
    }
}
公共类ListItemDataProvider扩展了AbstractBackEndDataProvider{
//...
@凌驾
从后端获取受保护的流(查询){
// ...
List fetchedResults=service.fetch(query.getOffset(),query.getLimit(),orderBy,getFilter(query));
fireEvent(新的FilteredDataFetchedEvent(这个,fetchedResults));
返回fetchedResults.stream();
}
}
@控制器
@范围(可配置BeanFactory.Scope\u原型)
公共类ItemListPresenter{
// ...
public void addFilteredDataFetchedListener(ItemListView.FilteredDataFetchedListener listener){
eventRouter.addListener(FilteredDataFetchedEvent.class,listener,FilteredDataFetchedListener.FILTERED\u DATA\u FETCHED);
}
}
几点注意:

  • 这不是我所需要的。是的,我可以使用我的大多数用例,如果应用了过滤器,列表将被重新加载,而详细信息视图也将获得要重新加载的事件。但是我不能为此重复使用“selectionChanged”事件监听器,实际上根本不能选择网格中的一行(只是因为
    DataProDriver
    中的事件在网格更新之前抛出)
  • 这是一种肮脏的把戏,因为现在
    dataProvider
    抛出事件并处理视图/演示者的
    eventrouter
    。另一方面,Vaadins数据提供程序无论如何都允许订阅事件。使用开箱即用的网格数据提供程序反应式绑定,我们只是在获取数据后不触发事件,所以我们以自定义方式执行
  • 还可以使用给定Vaadin的订阅服务器
    数据提供程序.addDataProviderListener
    ,从那里委托一个包含已填充筛选器的事件,并在“详细信息”面板中独立捕获该事件。但是,您将需要执行两次sql查询(这可能会很昂贵)或缓存它们等。与给定的查询相比,这不会带来任何好处,而且仍然是一种折衷
    调用dataprovider.refreshAll()时,关联的网格将自动刷新。因此,在代码中的以下行之后:

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

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

    是否无法在
    dataprovider.setFilter(filter)之后添加所需的自定义代码在您的submitButton clicklistener中?然后筛选器应该已经生效。否,设置筛选器将触发事件以获取刷新的筛选数据。此时您不知道结果是什么(计算行数),当然也不能在网格上调用select(),因为网格中仍然充满了旧数据(在获取数据之前)。
    
    filterBinder.writeBean(filter);
    dataProvider.setFilter(filter);