侦听器排序后 PrimeFaces DataTable 渲染列表错误(错误?)
PrimeFaces DataTable rendering list wrong after listener sort (bug?)
DataTable
会刷新,但无法正确呈现列表。 (JSF 2.2、Mojarra 2.2.0、PrimeFaces 5.2)
我在 PrimeFaces DataTable
中有一个日期列表,每次用户添加或编辑日期时我都会重新排序。这几乎完美无缺。请帮我看看我做错了什么,或者让我知道我发现了一个错误。 (注意,它不是 update
目标,因为我尝试使用 update="@all"
并没有改变任何东西。)
用下面的代码试试这个:
1) 添加 11/21/2015 然后添加 11/20/2015。请注意,它重新排序了它们 onAdd
.
控制台:
onAdd, after
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015]
DataTableEntry[Date:Sat Nov 21 00:00:00 EST 2015]
2) 然后编辑 11/21/2015 将其更改为 11/19/2015。请注意,编辑过的那个消失了,现在有两个 20's。 错误?!?
控制台:
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) 然后点击我的 "Refresh page" 命令按钮。它现在可以正确显示。
无论其 before/between/after 位置如何,添加日期都不会出现问题。我发现你可以编辑日期,只要它实际上不改变顺序,它就可以正常工作。顺序一改变,编辑过的就会消失,旁边的会被复制到原来的位置。
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()+"]";
}
}
我遇到了同样的问题
解决方法:在 <p:dataTable widgetVar="datatableVar" ...>
中定义 widgetVar 属性,并将此行添加到 onRowEdit 函数的末尾:
RequestContext.getCurrentInstance().execute("PF('datatableVar').filter()");
这将强制呈现整个数据表。
DataTable
会刷新,但无法正确呈现列表。 (JSF 2.2、Mojarra 2.2.0、PrimeFaces 5.2)
我在 PrimeFaces DataTable
中有一个日期列表,每次用户添加或编辑日期时我都会重新排序。这几乎完美无缺。请帮我看看我做错了什么,或者让我知道我发现了一个错误。 (注意,它不是 update
目标,因为我尝试使用 update="@all"
并没有改变任何东西。)
用下面的代码试试这个:
1) 添加 11/21/2015 然后添加 11/20/2015。请注意,它重新排序了它们 onAdd
.
控制台:
onAdd, after
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015]
DataTableEntry[Date:Sat Nov 21 00:00:00 EST 2015]
2) 然后编辑 11/21/2015 将其更改为 11/19/2015。请注意,编辑过的那个消失了,现在有两个 20's。 错误?!?
控制台:
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) 然后点击我的 "Refresh page" 命令按钮。它现在可以正确显示。
无论其 before/between/after 位置如何,添加日期都不会出现问题。我发现你可以编辑日期,只要它实际上不改变顺序,它就可以正常工作。顺序一改变,编辑过的就会消失,旁边的会被复制到原来的位置。
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()+"]";
}
}
我遇到了同样的问题
解决方法:在 <p:dataTable widgetVar="datatableVar" ...>
中定义 widgetVar 属性,并将此行添加到 onRowEdit 函数的末尾:
RequestContext.getCurrentInstance().execute("PF('datatableVar').filter()");
这将强制呈现整个数据表。