基于自定义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。不过这种方式代码量更大,适合需要多条件组合过滤、匹配模式(如包含、等于)等复杂场景。核心步骤是:
- 创建自定义类实现
FilterableQueryDescriptor,定义过滤规则; - 在Bean中创建该类的实例,绑定到table的
filterModel属性; - 重写过滤逻辑,将模型中的过滤条件应用到POJO集合。
不过对于大多数简单场景,上面的自定义输入框方式已经足够灵活和易用。
内容的提问来源于stack exchange,提问作者Sumit Ghosh
相关产品推荐
相关产品推荐

