java - 如何在 Vaadin Flow 中使用带有 DataProvider 的自定义组合框过滤?

标签 java combobox vaadin vaadin-flow

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

我在看这个Vaadin documentation关于如何实现组合框的自定义过滤。更具体地说,Filtering by a string 部分看起来很有前途。

根据 Vaadin 文档,我们实现了一个自定义接口(interface),用于调整 ComboBox 的搜索方法:

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

这非常简单,与文档示例几乎 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);
   });
}

我们在为 ComboBox 初始化数据时调用上述方法。在这一点上,我们还实现了接口(interface)(尽管这可能很难看)。然而,我们不太确定如何使用这两种接口(interface)方法。我们的第一个目标是始终返回所有项目并忽略任何特定的过滤,这就是我们始终返回整个 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,就会发生以下异常:

数据提供者返回的项目数超过了查询指定的限制 (1)。

我们的猜测是,我们必须以某种方式调整 getCountfetch 方法,使其实现我们的自定义搜索。这不会有问题,因为我们有 ComboBox 和 filterText 背后的数据。为什么我们还需要一个 getCount 方法以及我们如何绕过显示的异常?我们的想法是让 getCount 总是像 10 一样返回,并且在 fetch 中返回我们的 sorted 列表的子集过滤文本

谁能详细说明/帮助我们如何为 ComboBox 实现自定义过滤或为我们指明正确的轨道?


感谢 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 仅实现适用的 DataProvider 接口(interface)。之后,我们可以简单地应用 filteringByPrefix 方法来更改过滤行为。

最佳答案

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

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

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

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

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

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

使用 ListDataProvider

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

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

或者实现你自己的DataProvider

您可以实现自己的 DataProvider。我建议首先扩展 AbstractBackendDataProvider 类 ( javadoc )。需要实现方法 sizeInBackendfetchFromBackend。请注意 offset/limit 参数以在 fetch 方法中实现分页。

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

关于java - 如何在 Vaadin Flow 中使用带有 DataProvider 的自定义组合框过滤?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57921932/

相关文章:

java - Vaadin 8.5.1-行更新后刷新网格

java - 如何使用 jOOQ 处理自定义 SGBD 类型

java - 在另一个类中使用数组并停止随机数据

java - Eclipse 中的 "compiler compliance level"是什么?

java - 如何在 Spring Boot 中使用 Apache Kafka 的数据

Java Raspberry PI Help 是 Vaadin 的最佳方式吗?

c# - WPF 的自动完成组合框

c++ - 在 C++ 中刷新组合框?

c# - 组合框不在 C# 的 DataGridView 中显示默认值

java - CallbackDataProvider的fetchCallback没有回调,所以网格为空