2013-07-03 50 views
1

我正在处理JSF页面上的rich:datatable。该表可以变得非常大,并使用丰富的:datascroller进行分页。大多数列是硬连线的,并且总是在那里,但是随后有一些基于附加值的可选列,这些列需要为每个潜在附加值生成。我已经能够轻松地做到这一点。但是,我遇到了一个过滤问题。JSF:丰富的数据过滤,动态列和传递参数

我在每列上使用了一个过滤器。它被放置在具有列标签和排序功能的标题中。这对于每一列都有效,但由于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> 

The ???将很快涉及。至于过滤豆:

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列表中的索引,但这并没有帮助,因为我无法告诉它搜索每一行...

回答

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]); 
    } 
} 

而在XHTMLs使用它,如下所示:

<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

Ë dit2:不用编写FilterMethodWrapper,你也可以使用Predicate-implementation,并在前端使用apply-method(或者根据这个提议编写自己的Predicate-implementation,这个FilterMethodWrapper比此FilterMethodWrapper更易于使用)