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

时间:2013-07-03 15:59:10

标签: java jsf filter richfaces el

我正在研究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>

???将很快介绍。至于过滤豆:

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绑定到hashMap中的预设字符串,该字符串在方法中检索并用于过滤,因此我不需要为每个过滤器使用单独的字段。这工作得很好,但我仍然需要一个单独的方法为每个过滤器,这带我到???在JSF代码中......

我想要做的是将参数传递给过滤器方法以考虑动态列。实际上,我想用单个过滤器方法简化整个类,并将映射的String与当前对象中的字段一起传递。但是,这不起作用。我试过了:

filterMethod="#{filterBean.filterStuff(b, 'Field1')}" 

但是我最终得到了过滤字符串,但是当前对象为null。我不确定发生了什么。如果我正确地读取项目中的依赖项,我正在使用一些相当旧版本的EL,JSF,JSP等,而我真的无法改变它。不过,该项目确实使用了Seam,并且在此项目之前我已经成功地在EL中传递了参数。只是EL 2.2支持传递对象,而旧版本只支持原语和字符串吗?我有什么方法可以实现这一目标,还是我没有从头开始构建大量额外的东西而陷入困境?

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

1 个答案:

答案 0 :(得分:1)

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

用例:我有几个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:您可以使用一些Predicate实现并使用前端中的apply-method(或根据此提议编写自己的Predicate实现,而不是编写FilterMethodWrapper),而不是编写FilterMethodWrapper,而不是编写FilterMethodWrapper。 p>