在 Vaadin 8.2 中,我有一个使用数据提供程序 (AbstractBackEndDataProvider) 绑定(bind)到 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) {
//...
}
});
当数据提供者更新过滤器时,它会调用一个服务来从数据库中获取新项目并应用过滤器(对数据库查询)。 Vaadin 负责随后使用新数据刷新网格。
我想要的是在这最后一刻有一个回调。假设一个用例是检查过滤的提取结果集是否仅包含一个项目,以在网格中选择该项目(这将触发一个事件,在另一个 Pane 中显示项目详细信息)。或者在加载初始列表后选择第一个网格行
但问题是既没有grid.addRefreshListener()也没有dataProvider.addRefreshmentListener()。任何其他听众似乎都不适用于这种情况。
提前感谢您的帮助。
最佳答案
我找到的唯一解决方案是权衡取舍。
项目列表展示器(用网格处理 View )将其 com.vaadin.event.EventRouter
传递给 dataProvider
(我修改了 dataProvider
持有一个 EventRounter 作为成员)。现在,我不再直接从 dataProvider
流式传输 DB 结果,而是触发一个事件以获取数据(使用 EventRouter)。展示者可以订阅这个事件,然后委托(delegate)给详情面板的展示者。在那里你可以读取获取的结果(事件包含它们),检查是否只有一个条目并通过 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);
}
}
一些注意事项:
- 这不是我需要的。是的,我可以做我的大部分用例,如果应用过滤器,列表会重新加载,详细信息 View 也会让事件重新加载。但是我不能为此重新使用“selectionChanged”事件监听器,实际上根本无法在网格中选择一行(只是因为
dataProdiver
中的事件在网格更新之前被抛出). - 这是一个肮脏的把戏,因为现在
dataProvider
抛出事件并处理 View /演示者的eventRouters
。另一方面,Vaadins 数据提供者无论如何都允许订阅事件。使用开箱即用的 grid-dataProvider 响应式(Reactive)绑定(bind),我们只是在获取数据后没有触发事件,所以我们以自定义方式进行。 - 还可以使用给定的 Vaadin 订阅者
dataProvider.addDataProviderListener
并从那里委托(delegate)一个包含已填充过滤器的事件,然后在详细信息面板中独立捕获该事件。但是你需要执行两次 sql 查询(这可能是昂贵的)或缓存它们等。与给定的相比,这没有带来任何好处,仍然是一种权衡。
关于vaadin - 由数据提供者填充的网格 : how to trigger an action after refreshment?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48209978/