【问题标题】:Primefaces - custom component for live filtering in dataTablePrimefaces - 用于数据表中实时过滤的自定义组件
【发布时间】:2013-07-25 09:20:48
【问题描述】:

PrimeFaces 为 p:dataTable 提供了非常出色的过滤器。从 UX 站点来看它很棒,因为过滤器字段位于列标题中,所以毫无疑问您正在过滤什么,并且它正在实时工作 - 数据会随着您的输入而变化(好吧,只有当您短暂暂停时,但它在我的意见正是用户的期望)。

现在我想在标题中放置一些自定义内容作为过滤器。所以,我的想法是在 header facet 中放置一个组件:

<p:column ...>
  <f:facet name="header">
     <some:myComponent onkeydown="filterAction()"/>
  </f:facet>
</p:column>

问题是filterAction不能更新整个dataTable组件(因为用户输入的组件会被重新创建),但它必须更新表体。

我认为我可以使用 PrimeFaces 选择器(基于 jQuery 选择器)来做到这一点,但根据主题 How to update data rows only using a selector for dataTable? 这是不可能的。并且 datatable.js 包含专门的 Ajax 调用来实现这一点(行:PrimeFaces 3.5 中的 839,发布):

    options.onsuccess = function(responseXML) {
        var xmlDoc = $(responseXML.documentElement),
        updates = xmlDoc.find("update");
        ....
        $this.tbody.html(content);

我的问题是,是否可以使用这种单独的过滤器组件,它只会刷新表体,就像它所做的标准过滤器一样,而不需要深入到 PF 内部并编写专门的 AJAX 处理程序?

当然,也可以在dataTable之外做filter,但是这样会减少UX(现在使用我的应用的人很喜欢现在的设计)。

【问题讨论】:

    标签: jquery jsf-2 primefaces


    【解决方案1】:

    可以使用facet 将任何组件放在列标题中。但是,不能只请求数据表主体刷新。所以解决方案是,发送正常请求,但接管响应并在自定义代码部分进行处理。

    如果你这样创建 remoteCommand:

    <p:remoteCommand id="refreshDataTable" name="refreshDataTable"
                   actionListener="#{carTable.doFilter}" 
                   update="dataTable" />
    

    该命令的 ID 被发送到服务器。知道了这一点,我们就可以准备自定义的 AJAX 请求了:

     var options = {
            source: 'main:tabView:refreshDataTable',
            update: carsTable.id,
            formId: carsTable.cfg.formId
    }
    options.onsuccess = customHandler
    PrimeFaces.ajax.AjaxRequest(options);
    

    customHandler 代码如下所示:

    var xml = $(resp.documentElement)
    updates = xml.find('update')
    for(var i=0; i < updates.length; i++) {
    var update = updates.eq(i),
    id = update.attr('id'),
    content = update.text();
    if(id == carsTable.id){
       var tbody = $(content).find('tbody')
       carsTable.tbody.html(tbody.html());
    }
    else {
       PrimeFaces.ajax.AjaxUtils.updateElement.call(this, id, content);
    }
    PrimeFaces.ajax.AjaxUtils.handleResponse.call(this, xml);
    var paginator = carsTable.getPaginator();
    if(paginator) {
        paginator.setTotalRecords(this.args.totalRecords);
    }
    if(carsTables.cfg.scrollable) {
        carsTable.alignScrollBody();
    }
    return true;
    

    我们需要在Java代码中设置变量totalRecords:

        RequestContext context = RequestContext.getCurrentInstance();  
        context.addCallbackParam("totalRecords", filteredCars.size());  
    

    【讨论】:

      【解决方案2】:

      对于 Primefaces 5,有一个新属性 filterFunction 可以在 Java 代码中定义自定义过滤器:http://blog.primefaces.org/?p=3084

      但是,过滤器输入仍然是输入文本中的字符串。

      如果您需要一个自定义组件来输入过滤器值,或者您被 Primefaces 4 卡住(因为我在最近的一个项目中),我将描述什么对我有用。

      我使用这些关键步骤扩展了过滤行为

      • 将普通的 JSF 输入组件放入列的标题方面,而不是使用 filterBy 属性
      • 附加一个javascript回调到这个用户输入触发的组件,它调用PF('dataTableWidgetVar').filter()
      • 为dataTable添加filteredValue属性,在现有过滤器之上应用Java setter中的自定义过滤器

      关键是利用filteredValue 属性——当Primefaces filter() 函数被调用或primefaces 过滤器改变时,filteredValue 被设置为列出过滤后的值(如果没有应用过滤器,则为null)。然后 Primefaces 从 getter 中读回过滤值以更新 dataTable 中的项目列表。如果我们将过滤器放在这些调用之间(在 getter 或 setter 中,setter 效率更高,因为它仅在过滤器更改时调用),我们使用过滤器修改原始过滤列表并通过 getter 将其返回。

      一些代码:

      以inputText为过滤组件的数据表定义:

      <p:dataTable filteredValue="#{view.filteredResults} >
          ...
          <p:columnGroup type="header">
          ...
              <p:row>
          ...
                 <p:column>
                     <f:facet name="header">
                          <p:inputText value="#{view.filterValue}" />
                      </f:facet>
                 </p:column>
      
          ...
      </p:dataTable>
      

      视图命名视图中过滤结果的Java Setter和Getter:

      public void setFilteredResults(List<?> filteredResults) {
          this.filteredResults = applyPremiumFilters(filteredResults, filterValue);
      }
      
      public List<?> getFilteredResults() {
          return this.filteredResults;
      }
      

      剩下的是 Javascript 代码,用于在过滤器组件中的值更改时对 dataTable 应用过滤器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-01
        • 1970-01-01
        相关资源
        最近更新 更多