2015-11-04 65 views
1

DataTable会刷新,但不正确呈现列表。 (JSF 2.2,Mojarra 2.2.0,PrimeFaces 5.2)PrimeFaces DataTable呈现列表错误后,侦听器排序(bug?)

我有一个PrimeFaces DataTable中的日期列表,我每次用户添加或编辑日期时都要重新排序。这几乎完美地工作。请帮我看看我做错了什么,或者让我知道我发现了一个错误。 (请注意,它不是update目标,因为我尝试使用update="@all"这并没有改变任何东西。)

试试这个下面我的代码:

1)加入2015年11月21日再加入11/20/2015。注意它们将它们重新排序onAdd

enter image description here

控制台:

onAdd, after 
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015] 
DataTableEntry[Date:Sat Nov 21 00:00:00 EST 2015] 

2)然后编辑2015年11月21日将其更改为2015年11月19日。注意编辑过的一个走了,现在有两个20。 错误?!?

enter image description here

控制台:

onRowEdit, before 
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015] 
DataTableEntry[Date:Thu Nov 19 00:00:00 EST 2015] 
onRowEdit, after 
DataTableEntry[Date:Thu Nov 19 00:00:00 EST 2015] 
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015] 

3)然后打我的 “刷新页面” 命令按钮。它现在显示正确。

enter image description here

添加日期从未有一个问题,无论其前/间/位置后。我发现你可以编辑日期,只要它没有改变订单,它就可以正常工作。订单改变的那一刻,被编辑的消失,旁边的一个被视觉复制到它的位置。

datatablesort.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:p="http://primefaces.org/ui" 
    > 
<h:head> 
    <title><ui:insert name="title">DataTable</ui:insert></title> 
</h:head> 

<h:body> 
    <h:form id="modelerForm"> 
     <p:commandButton value="Refresh page" ajax="false"/> 

     <h:outputLabel for="date" value="Date"/> 
     <h:panelGroup> 
      <p:calendar id="date" pattern="MM/dd/yyyy" placeholder="mm/dd/yyyy" mask="true" showOn="button" navigator="true"/> 
      <h:commandButton value="Add"> 
       <f:ajax event="action" listener="#{dataTableBean.onAdd}" execute="date" render="entries"/> 
      </h:commandButton> 
     </h:panelGroup> 

     <p:dataTable id="entries" value="#{dataTableBean.entries}" var="entry" emptyMessage="No dates added" editable="true" tableStyle="width:auto"> 
      <p:ajax event="rowEdit" listener="#{dataTableBean.onRowEdit}" update="entries"/> 
      <p:column headerText="Dates"> 
       <p:cellEditor> 
        <f:facet name="output"> 
         <h:outputText value="#{entry.date}"> 
          <f:convertDateTime pattern="MM/dd/yyyy" /> 
         </h:outputText> 
        </f:facet> 
        <f:facet name="input"> 
         <p:calendar id="date" value="#{entry.date}" pattern="MM/dd/yyyy" placeholder="mm/dd/yyyy" mask="true" showOn="button" navigator="true"/> 
        </f:facet> 
       </p:cellEditor> 
      </p:column> 
      <p:column> 
       <p:rowEditor/> 
      </p:column> 
      <p:column> 
       <p:commandLink title="Remove date"> 
        <h:outputText value="" styleClass="ui-icon ui-icon-trash"/> 
        <f:ajax event="click" listener="#{dataTableBean.entries.remove(entry)}" render="entries"/> 
       </p:commandLink> 
      </p:column> 
     </p:dataTable> 
    </h:form> 
</h:body> 
</html> 

DataTableBean.java

package com.aadhoc.test; 

import java.util.ArrayList; 
import java.util.Comparator; 
import java.util.Date; 
import java.util.List; 

import javax.faces.bean.ManagedBean; 
import javax.faces.bean.SessionScoped; 
import javax.faces.component.UIComponent; 
import javax.faces.component.UIInput; 
import javax.faces.event.AjaxBehaviorEvent; 

import org.primefaces.component.datatable.DataTable; 
import org.primefaces.event.RowEditEvent; 

@ManagedBean(name="dataTableBean") 
@SessionScoped 
public class DataTableBean { 

    private List<DataTableEntry> entries = new ArrayList<>(); 
    public List<DataTableEntry> getEntries() { 
     return entries; 
    } 
    public void setEntries(List<DataTableEntry> entries) { 
     this.entries = entries; 
    } 

    public void onAdd(AjaxBehaviorEvent event) { 
     DumpList("onAdd, before"); 

     UIComponent component = event.getComponent(); 
     UIComponent dateComp = component.findComponent("date"); 
     Date date = (Date) ((UIInput)dateComp).getValue(); 
     DataTableEntry entry = new DataTableEntry(); 
     entry.setDate(date); 
     getEntries().add(entry); 

     sortEntries(getEntries()); 
     DumpList("onAdd, after"); 
    } 

    public void onRowEdit(RowEditEvent event) { 
     DumpList("onRowEdit, before"); 

     // Get entries via DataTable#getValue because in real code 
     // I don't have direct access to entries. 
     DataTable dt = (DataTable) event.getSource(); 
     @SuppressWarnings("unchecked") 
     List<DataTableEntry> entries = (List<DataTableEntry>) dt.getValue(); 
     sortEntries(entries); 

     DumpList("onRowEdit, after"); 
    } 

    private void DumpList(String msg) { 
     System.out.println(msg); 
     for (DataTableEntry entry : entries) { 
      System.out.println(entry); 
     } 
    } 

    private <T> void sortEntries(List<DataTableEntry> entries) { 
     entries.sort(new Comparator<DataTableEntry>() { 
      @Override 
      public int compare(DataTableEntry entry1, DataTableEntry entry2) { 
       return entry1.getDate().compareTo(entry2.getDate()); 
      } 
     }); 
    } 
} 

DataTableEntry.java

package com.aadhoc.test; 

import java.io.Serializable; 
import java.util.Date; 

public class DataTableEntry implements Serializable { 
    private static final long serialVersionUID = -2513940455250513641L; 
    private Date date; 
    public Date getDate() { 
     return date; 
    } 
    public void setDate(Date date) { 
     this.date = date; 
    } 

    public String toString() { 
     return getClass().getSimpleName()+"[Date:"+getDate()+"]"; 
    } 
} 
+0

我不知道为什么会发生,但是''的id是在中提到的“entries” 'rowEdit'事件应该更新整个不真实的数据表。 'rowEdit'事件默认为正在编辑的当前行。试图通过在“中提及它的id来更新数据表将被忽略。如果每次编辑行时需要更新整个数据表,则最好删除内联编辑,而改用“”。 – Tiny

+0

有趣的想法。我只是尝试用'update =“@ all”'和'update =“@ none”'来发现没有任何区别。也许它被忽略了。 'onAdd'在重新排序方面效果很好,但是您指出rowEdit的行为不同。作为一种替代方法,可以通过任何方式使其以可视方式强制进行非用户可更改的排序,而不是每次都使用模型? – AAron

+0

现在我已经禁用了每次添加/编辑时的排序,并打开了自然​​的列排序功能并将其设置为默认值。加载和刷新重新建立日期顺序,因为这种排序是默认的。如果我可以告诉它在每次添加/编辑之后使用'sortBy',我会拥有我想要的一切。 – AAron

回答

1

我遇到同样的问题。

解决方法:定义在<p:dataTable widgetVar="datatableVar" ...>widgetVar属性,并在您的onRowEdit函数的末尾添加下面一行:

RequestContext.getCurrentInstance().execute("PF('datatableVar').filter()"); 

这将迫使整个数据表的呈现。

+0

我相信你的答案有效。几个月后,我把我的项目从JSF转移开来。我希望我的帖子对你或其他人有帮助。谢谢! – AAron