Java JSF:丰富的数据表过滤、动态列和传递参数

Java JSF:丰富的数据表过滤、动态列和传递参数,java,jsf,filter,richfaces,el,Java,Jsf,Filter,Richfaces,El,我正在处理JSF页面上的rich:datatable。该表可能会变得相当大,并且页面上有一个rich:datascroller。大多数列都是硬连线的,并且将始终存在,但是还有一些基于附加值的可选列,这些附加值需要为每个潜在附加值生成。我已经很容易做到了。然而,我在过滤方面遇到了一个问题 我在每一列上使用一个过滤器。它与列标签和排序功能一起放置在标题中。这一点在每一列上都很好,但由于filtermethod在默认情况下的工作方式,我在过滤方面遇到了一个障碍。下面是一个简单的例子: <rich

我正在处理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>
但是我最终得到的过滤器字符串很好,但是对于当前对象为null。我不知道发生了什么事。如果我正确地阅读了项目中的依赖项,那么我正在使用一些非常旧的EL、JSF、JSP等版本,我真的没有办法改变这一点。不过,该项目确实使用了Seam,而且我以前在该项目中成功地在EL中传递了参数。只是EL2.2支持传递对象,而旧版本只支持原语和字符串吗?有没有什么办法让我做到这一点,或者我被困在没有从地面上建造一吨额外的东西


好的,看起来这在Seam中是可能的,但它不喜欢迭代变量。如果我从支持bean中引用列表中的索引,我可以传递对象,但这没有帮助,因为我无法告诉它搜索每一行…

我的用例有点不同,但基本上我遇到了相同的问题并找到了一个可行的解决方案

用例:我有几个XHTML文件及其支持bean,它们都提供了一个包含不同类型实体列表的表。在该表中,实体的某些属性有多个列,可以进行筛选。由于内置过滤器只执行“从开始”搜索,我需要更高级的搜索,因此我必须使用
filterMethod
。 但我不想让数百个简单的过滤方法完全相同(只不过属性不同),把我的备份bean搞得一团糟。所以我在寻找一种更通用的方法——这是我的方法:

在后端,我创建了一个名为
FilterMethodRapper
的新类(为了便于理解,我在这里将其作为嵌套静态类)和一个访问该类的方法:

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>

编辑:我正在使用JSF1.2和RichFaces 3.3.3.Final


Edit2:除了编写FilterMethodRapper,您还可以使用一些谓词实现并在前端使用apply方法(或者您根据这个方案编写自己的谓词实现,它比FilterMethodRapper更可重用)

我的用例有点不同,但基本上我也遇到了同样的问题,并找到了有效的解决方案

用例:我有几个XHTML文件及其支持bean,它们都提供了一个包含不同类型实体列表的表。在该表中,实体的某些属性有多个列,可以进行筛选。由于内置过滤器只执行“从开始”搜索,我需要更高级的搜索,因此我必须使用
filterMethod
。 但我不想让数百个简单的过滤方法完全相同(只不过属性不同),把我的备份bean搞得一团糟。所以我在寻找一种更通用的方法——这是我的方法:

在后端,我创建了一个名为
FilterMethodRapper
的新类(为了便于理解,我在这里将其作为嵌套静态类)和一个访问该类的方法:

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>

编辑:我正在使用JSF1.2和RichFaces 3.3.3.Final

Edit2:除了编写FilterMethodRapper,您还可以使用一些谓词实现,并在前端使用apply方法(或者您根据这个方案编写自己的谓词实现,它比这个FilterMethodRapper更可重用)