You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于自定义POJO列表在ADF的af:table中实现过滤遇阻求助

问题分析与解决方案

为什么过滤输入框是只读的?

ADF的af:table组件的内置过滤功能是**紧密绑定ADF Business Components(比如视图对象VO)**设计的。当你使用普通POJO列表作为数据源时,table无法找到对应的过滤支持逻辑——毕竟VO自带了查询、过滤的底层机制,而POJO只是普通Java对象集合,ADF不知道该如何将过滤输入和集合过滤关联起来。

你设置了filterable="true"和filterVisible="true",table会尝试启用内置过滤模式,但因为没有VO作为数据源支撑,它会自动将过滤输入框设为只读状态,这就是问题的根源。


解决方法:自定义过滤逻辑(无需VO)

最直接的方式是放弃依赖table的内置过滤属性,完全自定义列头的过滤输入框,手动实现过滤逻辑。具体步骤如下:

1. 修改页面代码

移除列上的filterable="true"属性,在列头的header facet中放置可编辑的输入框(可以搭配过滤按钮),确保输入框不受table内置过滤的干扰:

<af:table scrollPolicy="page" autoHeightRows="8" 
          value="#{myBean.pojoList}" var="myreport" id="t1" 
          styleClass="AFStretchWidth">
    <af:column headerText="Header1" width="10%">
        <f:facet name="header">
            <af:panelGroupLayout layout="horizontal" gap="5">
                <!-- 列标题 -->
                <af:outputText value="Header1" styleClass="AFHeaderText"/>
                <!-- 过滤输入框 -->
                <af:inputText simple="true" value="#{myBean.filterInput1}" 
                              autoSubmit="true" 
                              valueChangeListener="#{myBean.onFilterTextChange}"
                              immediate="true" shortDesc="输入内容过滤"/>
                <!-- 可选:手动触发过滤的按钮 -->
                <af:commandButton text="🔍" action="#{myBean.applyFilter}" 
                                  partialSubmit="true" immediate="true"/>
            </af:panelGroupLayout>
        </f:facet>
        <af:outputText value="#{myreport.data}"/>
    </af:column>
    <!-- 其他列 -->
</af:table>

2. 托管Bean中实现过滤逻辑

核心思路是保存原始数据集合,当用户输入过滤条件后,基于原始数据进行过滤,然后更新绑定到table的集合,最后局部刷新表格:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.faces.event.ValueChangeEvent;
import oracle.adf.view.rich.context.AdfFacesContext;

public class MyBean {
    // 保存从第三方服务获取的原始数据(避免每次过滤都调用服务)
    private List<MyReportPOJO> originalPojoList;
    // 绑定到table的过滤后数据
    private List<MyReportPOJO> pojoList;
    // 过滤输入框的值
    private String filterInput1;

    // 初始化方法:从第三方服务加载数据
    public void initReportData() {
        // 调用第三方服务获取数据
        originalPojoList = thirdPartyService.getReportData();
        // 初始化显示全部数据
        pojoList = new ArrayList<>(originalPojoList);
    }

    // 实时过滤(输入框内容变化时触发)
    public void onFilterTextChange(ValueChangeEvent event) {
        filterInput1 = (String) event.getNewValue();
        applyFilter();
    }

    // 应用过滤逻辑
    public void applyFilter() {
        if (filterInput1 == null || filterInput1.trim().isEmpty()) {
            // 过滤条件为空,显示全部数据
            pojoList = new ArrayList<>(originalPojoList);
        } else {
            // 根据输入条件过滤原始数据(支持大小写不敏感)
            pojoList = originalPojoList.stream()
                    .filter(item -> item.getData().toLowerCase().contains(filterInput1.toLowerCase()))
                    .collect(Collectors.toList());
        }
        // 局部刷新表格
        AdfFacesContext.getCurrentInstance().partialUpdateTarget("t1");
    }

    // Getter & Setter方法
    public List<MyReportPOJO> getPojoList() { return pojoList; }
    public void setPojoList(List<MyReportPOJO> pojoList) { this.pojoList = pojoList; }
    public String getFilterInput1() { return filterInput1; }
    public void setFilterInput1(String filterInput1) { this.filterInput1 = filterInput1; }
}

进阶方案:实现自定义FilterModel

如果你希望更贴近ADF内置过滤的体验(比如使用table的filterModel属性),可以实现ADF的FilterableQueryDescriptor接口,自定义过滤模型并绑定到table。不过这种方式代码量更大,适合需要多条件组合过滤、匹配模式(如包含、等于)等复杂场景。核心步骤是:

  1. 创建自定义类实现FilterableQueryDescriptor,定义过滤规则;
  2. 在Bean中创建该类的实例,绑定到table的filterModel属性;
  3. 重写过滤逻辑,将模型中的过滤条件应用到POJO集合。

不过对于大多数简单场景,上面的自定义输入框方式已经足够灵活和易用。


内容的提问来源于stack exchange,提问作者Sumit Ghosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:41:36