在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()。在这种情况下,任何其他听众似乎都不适用。
感谢您提前提供任何帮助。
答案 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);
}
}
很少注意到:
dataProdiver
的事件)。 / LI>
dataProvider
会抛出事件并与eventRouters
个观看者/演示者交易。另一方面,Vaadins数据提供者无论如何都允许订阅事件。使用那个开箱即用的grid-dataProvider反应绑定,我们只是在获取数据后没有触发事件,因此我们以自定义方式执行此操作。dataProvider.addDataProviderListener
,并从那里委托包含填充过滤器的事件,并在详细信息面板中独立捕捉该事件。但是,你需要执行两次sql查询(这可能是昂贵的)或缓存它们等。与给定的相比没有任何好处,仍然是一个权衡。 答案 1 :(得分:0)
调用dataprovider.refreshAll()时,将自动刷新关联的网格。因此,在代码中的以下几行之后:
filterBinder.writeBean(filter);
dataProvider.setFilter(filter);
添加逻辑以获取返回记录的大小(例如dataprovider.size()),如果该值等于一个(01),则调用其他逻辑以选择一个记录并在另一面板中显示其详细信息。