2

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

现在我想在标题中放置一些自定义的东西作为过滤器。所以,我的想法是在标题方面放置一个组件:

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

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

我认为我可以使用PrimeFaces 选择器(基于 jQuery 选择器)来做到这一点,但根据主题如何仅使用数据表的选择器更新数据行?这不可能。并且 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(现在使用我的应用的人很喜欢现在的设计)。

4

2 回答 2

3

可以使用 . 将任何组件放在列标题中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());  
于 2013-07-26T17:52:45.190 回答
1

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

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

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

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

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

关键是利用filteredValue 属性——当Primefaces filter() 函数被调用或primefaces 过滤器改变时,filteredValue 设置为列出过滤值(如果没有应用过滤器,则为null)。然后 Primefaces 从 getter 中读回 filtersValues 以更新 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 应用过滤器。

于 2014-07-09T14:12:15.373 回答