如何在 Vaadin Flow 中将自定义组合框过滤与 DataProvider 结合使用?

LOL*_*dad 3 java combobox vaadin vaadin-flow

我们当前使用的是 Vaadin Flow 版本 12.0.7(由于某些原因我们无法升级),并且我们希望覆盖 ComboBox 组件的过滤机制。我的意思是,当用户在组合框内输入输入时,我们希望更改组合框后面的项目的搜索方式。

我正在查看Vaadin 文档,了解如何实现组合框的自定义过滤。更具体地说,该部分Filtering by a string看起来很有希望。

根据 Vaadin 文档,我们实现了一个自定义接口来适应 ComboBox 的搜索方法:

public interface CustomerDataFilter {
    List<Customer> fetch(int offset, int limit, String filterText);
    int getCount(String filterText);
}
Run Code Online (Sandbox Code Playgroud)

这非常简单,并且与文档示例几乎 1:1 匹配。

然后,我们根据文档创建了一个方法,用数据填充 ComboBox。文档中也几乎使用了 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);
   });
}
Run Code Online (Sandbox Code Playgroud)

我们在初始化 ComboBox 的数据时调用上述方法。此时我们还实现了接口(尽管这可能很难看)。然而我们不太确定如何使用这两个接口方法。我们的第一个目标是始终返回所有项目并忽略任何特定过滤,这就是我们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);
}
Run Code Online (Sandbox Code Playgroud)

我们尝试将该getCount值增加到1,但一旦我们将其设置为高于0以下异常,就会发生:

The number of items returned by the data provider exceeds the limit specified by the query (1).

我们的猜测是,我们必须以某种方式调整getCountfetch方法,以便它们实现我们的自定义搜索。这不会有问题,因为我们有 ComboBox 和filterText. 我们怎么有点困惑为什么我们getCount还需要一个方法以及如何绕过显示的异常?我们的想法是让getCountalways 返回like10fetch返回我们列表中sorted关于filterText.

任何人都可以详细说明/帮助我们如何实现组合框的自定义过滤或为我们指出正确的轨道吗?


感谢 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()));
}
Run Code Online (Sandbox Code Playgroud)

唯一CustomerProvider实现适用的 DataProvider 接口。之后我们可以简单地应用该filteringByPrefix方法来更改过滤行为。

Ste*_*ich 5

您走在正确的轨道上,但您需要首先了解概念DataProvider

在客户端(浏览器),一旦用户与其进行交互,Vaadin 就会请求将数据显示在组合框中。请求的数据类似于“数据中有多少项?” 这是计数查询。假设您有 100 件商品。现在,下一个请求是“给我要显示的前 40 个项目”,这是获取查询。组合框将显示返回的项目。一旦用户向下滚动列表,就会发出另一个数据请求“给我接下来要显示的 40 个项目”等。

总而言之,DataProvider首先要求返回所有项目的计数,然后根据需要逐页获取数据。当用户输入过滤器时这也适用。不同之处在于您的计数和获取查询应考虑过滤器。

示例:用户输入了过滤器“xyz”,现在只有 50 个项目与此过滤器匹配(通过名称或其他内容),因此您将在 count 方法中返回 50,并且您的 fetch 方法应该相应地进行过滤。

您遇到的异常只是指出您的 fetch 方法返回的项目多于 Vaadin 请求的项目(查询参数中的“limit”参数)。这是因为您当前不处理偏移/限制。

您有两种选择来实施您的数据提供程序:

使用列表数据提供者

Vaadin 提供了for 列表ListDataProvider的实现DataProvider。分页已经在实现中完成了,你不必关心它。使用该filteringBy方法根据输入的过滤文本过滤数据。

这种方式更容易,但不可扩展。这意味着如果您有很多项目,您将消耗大量内存和 CPU,因为整个数据都是从后端检索到列表中的。如果您预计商品数量较少,请采用此方法。

或者实现您自己的 DataProvider

您可以实现自己的DataProvider. 我建议从扩展AbstractBackendDataProvider类(javadoc)开始。方法sizeInBackendfetchFromBackend需要实施。请注意在 fetch 方法中实现分页的偏移/限制参数。

如果您将分页委托给数据库(例如 SQL 或 no-sql 数据库),则此方法是可扩展的。内存占用会很低,因为您只在内存中保留一页。