2015-11-04 60 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