我正在 JSF 页面上处理 rich:datatable。该表可以变得相当大,并使用 rich:datascroller 进行分页。大多数列都是硬连线的并且始终存在,但也有一些基于需要为每个潜在附加值生成的附加值的可选列。我已经能够很容易地做到这一点。但是,我遇到了过滤问题。
我在每列上使用过滤器。它与列标签和排序功能一起放置在标题中。每列都工作得很好,但由于 filtermethod 默认的工作方式,我在过滤时遇到了障碍。这是一个简单的示例:
<rich:datatable id="thetable" value=#{backingBean.stuff} var="b">
<!-- First column, standard filter method, works just fine -->
<rich:column sortBy="#{b.field1}" filterMethod="#{filterBean.filterField1}">
<f:facet name="header">
<ui:fragment>
<h:outputText value="Field 1" />
<h:inputText value="#{filterBean.filterMap['Field1']}" />
</ui:fragment>
</f:facet>
#{b.field1}
</rich:column>
<c:forEach items="#{backingBean.extraStuff}" var="e">
<rich:column sortBy="#{b.getExtra(e)}" filterMethod="???">
<f:facet name="header">
<ui:fragment>
<h:outputText value="#{b.getExtra(e).description}" />
<h:inputText value="#{filterBean.filterMap['b.getExtra(e).code']}" />
</ui:fragment>
</f:facet>
#{b.getExtra(e).description}
</rich:column>
</rich:datatable>
这个???很快就会涵盖。至于过滤器bean:
public class FilterBean {
public Map<String, String> filterMap = new HashMap<String, String>();
public boolean filterField1(Object current){
return ((BackingBean) current).contains(filterMap.get("Field1"));
}
}
这相当简单。过滤器 inputText 绑定(bind)到 hashMap 中的预设字符串,该字符串在方法中检索并用于过滤,因此我不需要为每个过滤器使用单独的字段。这很好用,但我仍然需要为每个过滤器使用单独的方法,这将我带到了???在 JSF 代码中...
我想做的是将参数传递给过滤器方法以考虑动态列。事实上,我想用一个过滤器方法来简化整个类,并将映射的字符串与当前对象的字段一起传递。但是,这不起作用。我尝试过:
filterMethod="#{filterBean.filterStuff(b, 'Field1')}"
但我最终得到的过滤字符串很好,但当前对象为空。我不确定发生了什么事。如果我正确地读取了项目中的依赖项,那么我正在使用一些相当旧的 EL、JSF、JSP 等版本,而且我确实没有办法更改它。不过,该项目确实使用了 Seam,而且我之前在该项目中已经在 EL 中成功传递了参数。难道只是 EL 2.2 支持传递对象,而旧版本仅支持原语和字符串吗?我有什么办法可以实现这一点,还是我在没有从头开始构建大量额外东西的情况下陷入困境?
好吧,看起来 Seam 可以做到这一点,但它不喜欢迭代变量。如果我从支持 bean 引用列表中的索引,我可以传递该对象,但这没有帮助,因为我无法告诉它搜索每一行...
最佳答案
我的用例有点不同,但基本上我遇到了同样的问题并找到了一个可行的解决方案。
用例:我有几个 XHTML 文件,它们的支持 bean 都提供一个包含不同类型实体列表的表。在此表中,有几列用于可以过滤的实体的某些属性。由于内置过滤器仅执行“开头为”搜索,而我需要更高级的搜索,因此我必须使用 filterMethod
。
但我不想用数百个简单的过滤方法搞乱我的支持 bean,这些方法的作用完全相同(仅具有不同的属性)。所以我正在寻找一种更通用的方法 - 这就是我的方法:
在后端,我创建了一个名为 FilterMethodWrapper
的新类(为了更容易理解,我将其放置为嵌套静态类)以及访问它的方法:
import org.apache.commons.beanutils.PropertyUtils;
public class BackendBean
{
private String[] filterValues;
// initialize filterValues somewhere, add getter and setter
public static class FilterMethodWrapper
{
private final String fieldName;
private final String filterValue;
public FilterMethodWrapper(final String fieldName, String filterValue)
{
this.fieldName = fieldName;
this.filterValue = filterValue;
}
public boolean doFilter(Object current) throws ...
{
final String stringValue = (String) PropertyUtils.getSimpleProperty(current, fieldName);
// compare stringValue and filterValue somehow (e.g. contains)
// and return result
}
}
public FilterMethodWrapper getFilterMethodWrapper(String fieldName, int filterValueIndex)
{
return new FilterMethodWrapper(fieldName, getFilterValues()[filterValueIndex]);
}
}
在 XHTML 中按如下方式使用它:
<rich:column filterMethod="#{backendBean.getFilterMethodWrapper('username', 0).doFilter}" filterEvent="onkeyup" >
<f:facet name="header">
<h:panelGrid style="display:inline;">
<h:outputText value="Username"/>
<h:inputText value="#{backendBean.filterValues[0]}" />
</h:panelGrid>
</f:facet>
<h:outputText value="#{_item.username}" />
</rich:column>
编辑:我正在使用 JSF 1.2 和 RichFaces 3.3.3.Final
Edit2:除了编写 FilterMethodWrapper 之外,您还可以使用一些 Predicate-implementation 并在前端使用 apply-method (或者您根据此提案编写自己的 Predicate-implementation,它比 FilterMethodWrapper 更具可重用性)
关于java - JSF:丰富的数据表过滤、动态列和传递参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17452742/