[英]Updating entire <p:dataTable> on complete of <p:ajax event="cellEdit">
編輯單元格后,我很難重新渲染 PrimeFaces 數據表。 更改一個單元格中的值可能會更改其他單元格中的條目,因此需要刷新整個表格。
這是 JSF 頁面:
<h:form id="testForm">
<p:outputPanel id="testContainer">
<p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
<p:column headerText="Col1">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.col1}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.col1}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Col2">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.col2}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.col2}" /></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
<p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />
</p:outputPanel>
</h:form>
這是支持bean:
@ManagedBean(name = "tableBean", eager = false)
@ViewScoped
public class TableBean {
public TableBean() {
RowData entry = new RowData("a1", "b1");
entries.add(entry);
entry = new RowData("a2", "b2");
entries.add(entry);
entry = new RowData("a3", "b3");
entries.add(entry);
}
public class RowData {
private String col1;
private String col2;
public RowData(String col1, String col2) {
this.col1 = col1;
this.col2 = col2;
}
public String getCol1() {
return col1;
}
public void setCol1(String col1) {
this.col1 = col1;
}
public String getCol2() {
return col2;
}
public void setCol2(String col2) {
this.col2 = col2;
}
}
private ArrayList<RowData> entries = new ArrayList<RowData>();
public List<RowData> getData() {
return entries;
}
public void onCellEdit(CellEditEvent event) {
entries.get(event.getRowIndex()).setCol1("Dummy Col 1");
entries.get(event.getRowIndex()).setCol2("Dummy Col 2");
}
}
當在 cellEdit AJAX 事件中包含 update=":testForm:testContainer" 時,更改單元格值會刪除屏幕上的數據表,並且只呈現單元格內容(連同按鈕)——我不明白這是為什么。 當未指定更新屬性時,表格將保留在屏幕上,活動單元格已更新,但其他單元格均未更新(正如預期的那樣)。
通過在 AJAX cellEdit 事件中不指定更新屬性並在編輯單元格的值后單擊重新顯示按鈕,可以實現所需的行為(以非自動方式)。 我怎樣才能以自動化的方式實現這一點,為什么更新屬性不能按我的預期工作?
我正在使用 PrimeFaces 4.0。
rowEdit
和cellEdit
事件按設計在表內不會更新/重新呈現當前行以外的任何內容,即使在update
屬性中明確指定時也不行。 這是 PrimeFaces 有點過分熱心地嘗試最小化響應大小的結果。 這在大多數情況下都有意義,但在您的情況下則不然。 值得一份問題報告。
同時,在他們修復此行為之前,最好的辦法是使用<p:remoteCommand>
調用所需的偵聽器方法並執行表的完整更新。
改寫
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
...
</p:dataTable>
到
<p:remoteCommand name="onCellEdit" action="#{tableBean.onCellEdit}" update="testContainer" />
<p:dataTable ...>
<p:ajax event="cellEdit" oncomplete="onCellEdit()" />
...
</p:dataTable>
BaLusC 解決方案並沒有直接為我工作。 onCellEdit 需要一個 CellEditEvent 作為參數。 我的解決方法如下:
<p:remoteCommand name="onCellEdit" update="testContainer" />
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" oncomplete="onCellEdit()" />
...
</p:dataTable>
如果沒有一個解決方案適合你,這對我有用
<p:dataTable ... id="theId" widgetVar="theWidget" ...>
<p:ajax event="rowEdit" listener="#{...}"
oncomplete="PF('theWidget').filter()"/>
....
我在 ajax complete 上調用 PF 小部件上的過濾器方法,任何對表進行“重新加載”的方法都應該工作,我使用了過濾器,因為我的表有列過濾器。
我測試了你的代碼。 首先,我將 p:commandButton 從 p:outputPanel 中移出。 這是修改后的代碼:
<h:form id="testForm">
<p:outputPanel id="testContainer">
<p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
(...)
</p:dataTable>
</p:outputPanel>
<p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />
</h:form>
我認為這段代碼不能正常工作。 如果您更改表中的任何內容,p:ajax 每次都會呈現完整的表。 因此,程序從 TableBean 構造函數加載基本數據並刪除新數據。
如果我省略您的 p:ajax 代碼,則不會從屏幕上消失任何新數據。 refreshButton
p:commandButton 工作正常。
當在 cellEdit AJAX 事件中包含 update=":testForm:testContainer" 時,更改單元格值會刪除屏幕上的數據表並且只呈現單元格內容(以及按鈕)——我不明白為什么會這樣。
我認為將update=":testForm:testContainer"
到 ajax 是不好的設計,因為它更新了你的 outputPanel 超過了例外(第一次正常工作,第二次無法編輯單元格,因為程序更新到多次表) .
我不知道你的目標是什么。 如果你想在沒有 commandButton 的情況下渲染表,那么你可以指定一個 javascript 事件或 p:message 並且這消失你可以渲染表。
我認為如果您在 p:ajax 中省略更新或指定一個 p:message 的更新,並將 p.commandButton 移出testContainer
您的代碼開始正常工作。
5年后,這個問題仍然存在。 不幸的是,雖然 Baukes 解決方案非常有用並且包含重要的見解,但它仍然不完整,正如 ltlBeBoy 在他的評論中已經指出的那樣。 沒有更改的后續編輯會導致表格狀態不一致,無法進行更多編輯。 原因是, oncomplete
遠程更新是在新單元格的編輯模式已經激活之后發生的。 所以新單元格的編輯模式被更新破壞了。 但是,不能在 Ajax 偵聽器tableBean#onCellEdit
,因為這會錯誤地顯示只有一個單元格的表格。
解決方案是,僅在發生更改時才在遠程命令偵聽器中執行更新。 因此,在tableBean
您實現了一個編程更新、一個遠程偵聽器和一個指示更改的標志:
public static void update(String id) {
PrimeFaces pf = PrimeFaces.current(); //RequestContext.getCurrentInstance() for <PF 6.2
if(pf.isAjaxRequest()) pf.ajax().update(id);
}
/** Whether onCellEdit changed the value */
boolean onCellEditChange;
public void onCellEditRemote() {
if(!onCellEditChange) update("testContainer");
}
public void onCellEdit(CellEditEvent event) {
... onCellEditChange= /*Change happend*/ ...
}
遠程命令不再有更新屬性:
<p:remoteCommand name="onCellEdit" actionListener="#{tabelBean.onCellEditRemote}"/>
嘗試使用過程
<p:remoteCommand name="onCellEdit" update="testContainer" process="@this" /> <p:dataTable ...> <p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" oncomplete ="onCellEdit()" process="@this" /> ... </p:dataTable>
這是我在這里的第一篇文章。 正如 ltlBeBoy 所提到的,BalusC 的解決方案只有在單元格編輯通過回車鍵完成時才有效。 此處列出的其他建議均不適合我。 就我而言,我只想在 cellEdit 事件上更新表中的特定行(具有每列的平均值)。 如果有人正在尋找解決方案,我會發布此信息:我設法通過在主數據表正下方的第二個數據表中分離該行來實現這一點。 這是代碼:
<pf:ajax event="cellEdit"
listener="#{newAgentMetricBacking.onCellEdit}"
update="c21413" />
<pf:dataTable id="c21413"
styleClass="noHeader"
value="">
<pf:column>
<h:outputText value="#{bundle.TeamAverage}"/>
</pf:column>
<pf:columns columnIndexVar="j"
value="#{newAgentMetricBacking.averageArray}"
var="avg">
<h:outputText value="#{newAgentMetricBacking.
averageArray[j]}"/>
</pf:columns>
</pf:dataTable>
否則,截至今天,我找不到更好的解決方案來更新整個表或特定行,特別是在 cellEdit 事件成功后。 干杯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.