java如何在Vaadin流中使用数据提供程序的自定义组合框过滤?
我们目前使用的是Vaadin Flow版本12.0.7(由于种种原因,我们无法升级),我们希望覆盖ComboBox组件的过滤机制。我的意思是,当用户在组合框中输入输入时,我们希望改变搜索组合框后面项目的方式
我正在研究如何实现组合框的自定义筛选。更具体地说Filtering by a string
一节看起来很有希望
根据Vaadin文档,我们实现了一个自定义界面,用于调整组合框的搜索方法:
public interface CustomerDataFilter {
List<Customer> fetch(int offset, int limit, String filterText);
int getCount(String filterText);
}
这是非常直截了当的,与文档示例的比例接近1:1
然后,我们根据文档创建了一个方法,用数据填充组合框。也几乎使用了文档中的1:1:
private DataProvider<Customer, String>
createDepartmentDataProvider(CustomerDataFilter service)
{
return DataProvider.fromFilteringCallbacks(query -> {
// getFilter returns Optional<String>
String filter = query.getFilter().orElse(null);
return service.fetch(query.getOffset(),
query.getLimit(), filter).stream();
}, query -> {
String filter = query.getFilter().orElse(null);
return service.getCount(filter);
});
}
我们在初始化组合框的数据时调用上述方法。在这一点上,我们还实现了接口(尽管可能很难看)。然而,我们不太确定如何使用这两种接口方法。我们的第一个目标就是始终返回所有项目,忽略任何特定的筛选,这就是为什么我们始终返回整个sorted
列表的原因。这只是为了测试我们是否改变了过滤
public void updateCustomerList() {
List<Customer> sorted = CustomerService.getInstance().findAll();
//for initial sorting
sorted.sort(new CustomerComperator());
DataProvider<Customer, String> test = createDepartmentDataProvider(new CustomerDataFilter() {
@Override
public int getCount(String filterText) {
return 0;
}
@Override
public List<Customer> fetch(int offset, int limit, String filterText) {
return sorted;
}
});
customerCompany.setItems(sorted);
customerCompany.setDataProvider(test);
}
我们试图将getCount
值增加到1
,但一旦我们将其设置为高于0
,就会出现以下异常:
The number of items returned by the data provider exceeds the limit specified by the query (1).
我们的猜测是,我们必须以某种方式调整getCount
和fetch
方法,以实现我们的customsearch。这不会有问题,因为我们在组合框和filterText
后面有数据。我们怎么会有点困惑,为什么我们也需要一个getCount
方法,以及我们如何绕过显示的异常?我们的想法是让getCount
总是像10
一样返回,并在fetch
中返回关于filterText
的sorted
列表的子集
有没有人能详细说明/帮助我们如何实现组合框的自定义过滤,或者为我们指出正确的方向
感谢Steffen Harbichs的回答,我们找到了实现过滤数据提供者的方法。基本上这就是所需要的一切:
public void updateCustomerList() {
List<Customer> sorted = CustomerService.getInstance().findAll();
sorted.sort(new CustomerComperator());
customerCompany.setItems(sorted);
ListDataProvider<Customer> listTest = new ListDataProvider<>(sorted);
customerCompany.setDataProvider(listTest.filteringByPrefix(new CustomerProvider()));
}
CustomerProvider
仅实现适用的数据提供程序接口。然后,我们可以简单地应用filteringByPrefix
方法来更改过滤行为
# 1 楼答案
您的思路是正确的,但首先需要理解^{} 的概念
在客户端(浏览器),一旦用户与Vaadin进行了一些交互,Vaadin请求将数据显示在组合框中。请求的数据将类似于“数据中有多少项?”这是计数查询。假设你有100件物品。现在,下一个请求是“给我前40个要显示的项目”,这是获取查询。组合框将显示返回的项目。一旦用户向下滚动列表,就会发出另一个数据请求“给我接下来要显示的40个项目”等
总之,首先要求
DataProvider
返回所有项的计数,然后根据需要逐页获取数据。这也适用于用户输入过滤器的情况。不同之处在于,计数和获取查询应该考虑过滤器示例:用户输入的筛选器“xyz”,现在只有50个项与此筛选器匹配(按名称或其他内容),所以您将在count方法中返回50个项,并且您的fetch方法将相应地进行筛选
您遇到的异常只是指出,fetch方法返回的项目比Vaadin请求的多(查询参数中的“limit”参数)。这是因为您当前不处理偏移/限制
您有两个选项来实现数据提供程序:
使用ListDataProvider
Vaadin提供了^{} ,这是列表
DataProvider
的一个实现。分页已经在实现中完成,您不必关心它。使用filteringBy
方法根据输入的筛选文本筛选数据这种方法更简单,但不具有可扩展性。这意味着,如果您有许多项,您将消耗大量内存和CPU,因为整个数据都是从后端检索到列表中的。如果你认为你的物品数量很低,那么就采用这种方法
或者实现您自己的数据提供者
您可以实现自己的
DataProvider
。我建议首先扩展AbstractBackendDataProvider
类(javadoc)。需要实现方法sizeInBackend
和fetchFromBackend
。注意在fetch方法中实现分页的offset/limit参数如果将分页委托给数据库(例如SQL或无SQL数据库),则此方法是可扩展的。内存占用将很低,因为您只需在内存中保留一页