2013-07-03 74 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更易於使用)