Primefaces Bean 对象未正确更新
Primefaces Bean Object isn't updated correctly
我遇到了以下问题。我有一个 XHTML:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
template="../layout.xhtml">
<ui:define name="header">
<div id="header">
Abfragen
</div>
</ui:define>
<ui:define name="main">
<p:toolbar>
<p:toolbarGroup>
<p:commandButton value="Neu" icon="pi pi-plus" actionListener="#{abfrageHandler.newAbfrage}"
update="manage-queries-content" oncomplete="PF('manageQueriesDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<p:resetInput target=":ucmdbform:ucmdbtab:manage-ucmdb-queries-content"/>
</p:commandButton>
</p:toolbarGroup>
</p:toolbar>
<p:dataTable id="dt-queries" widgetVar="dtQueries" reflow="true" showGridlines="true" size="small"
var="querie" value="#{abfrageHandler.abfragen}">
<p:column headerText="Abfrage">
<h:outputText value="#{querie.name}" />
</p:column>
<p:column headerText="TQL">
<h:outputText value="#{querie.tql}" />
</p:column>
<p:column headerText="Zyklus">
<h:outputText value="#{querie.zyklus}" />
</p:column>
<p:column headerText="Typ">
<h:outputText value="#{querie.typ}" />
</p:column>
<p:column exportable="false">
<p:commandButton icon="pi pi-pencil" update="manage-queries-content"
oncomplete="PF('manageQueriesDialog').show()"
styleClass="edit-button rounded-button ui-button-success" process="@this">
<f:setPropertyActionListener value="#{querie}" target="#{abfrageHandler.selected}"/>
<p:resetInput target="manage-queries-content"/>
</p:commandButton>
<p:commandButton icon="pi pi-search" actionListener="#{abfrageHandler.startAbfrage(querie)}"
styleClass="edit-button rounded-button ui-button-success" process="@this">
</p:commandButton>
<p:commandButton class="ui-button-warning rounded-button" icon="pi pi-trash" process="@this"
oncomplete="PF('deleteQuerieDialog').show()">
<f:setPropertyActionListener value="#{querie}" target="#{abfrageHandler.selected}"/>
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Abfrage" showEffect="fade" modal="true" width="600px"
widgetVar="manageQueriesDialog" responsive="true">
<p:outputPanel id="manage-queries-content" class="ui-fluid">
<p:outputPanel rendered="#{not empty abfrageHandler.selected}">
<div class="p-field">
<p:outputLabel for="abfName">Name</p:outputLabel>
<p:inputText id="abfName" value="#{abfrageHandler.selected.name}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="abfTql">TQL</p:outputLabel>
<p:inputText id="abfTql" value="#{abfrageHandler.selected.tql}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="abfZyklus">Zyklus</p:outputLabel>
<p:inputText id="abfZyklus" value="#{abfrageHandler.selected.zyklus}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="@next">Abfrageart</p:outputLabel>
<p:selectOneMenu id="abfTyp" value="#{abfrageHandler.selected.typ}" required="false">
<f:selectItem itemLabel="Eins wählen" itemValue=""/>
<f:selectItems value="#{abfrageHandler.requestResolutions}" var="reso"
itemLabel="#{reso.toString()}" itemValue="#{reso}"/>
</p:selectOneMenu>
</div>
</p:outputPanel>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Speichern" icon="pi pi-check" actionListener="#{abfrageHandler.saveAbfrage}"
update="manage-queries-content" process="manage-queries-content @this"/>
<p:commandButton value="Abbruch" icon="pi pi-times" onclick="PF('manageQueriesDialog').hide()"
class="ui-button-secondary"/>
</f:facet>
</p:dialog>
<p:confirmDialog widgetVar="deleteQuerieDialog" showEffect="fade" width="300"
message="TQL wirklich löschen?" header="Bestätigen" severity="warn">
<p:commandButton value="Ja" icon="pi pi-check" actionListener="#{abfrageHandler.deleteParameter}"
process="@this" oncomplete="PF('deleteQuerieDialog').hide()"/>
<p:commandButton value="Nein" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
onclick="PF('deleteQuerieDialog').hide()"/>
</p:confirmDialog>
</ui:define>
</ui:composition>
以及后端中的以下 bean:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.primefaces.PrimeFaces;
import main.java.ucmdbtool.RequestResolutions;
import main.java.ucmdbtool.UcmdbAbfrageInteface;
import main.java.ucmdbtool.table.Abfrage;
import main.java.ucmdbtool.table.UcmdbAbfTableHandler;
@SuppressWarnings("serial")
@Named("abfrageHandler")
@ViewScoped
public class AbfrageHandler implements Serializable {
private List<Abfrage> abfragen = new ArrayList<>();
private Abfrage selected;
private RequestResolutions[] requestResolutions;
@PostConstruct
private void init() {
abfragen = UcmdbAbfTableHandler.getAbfragen();
requestResolutions = RequestResolutions.values();
}
public void newAbfrage() {
selected = new Abfrage();
}
public void saveAbfrage() {
if (selected.getPk() == null) {
selected.setPk(UUID.randomUUID());
UcmdbAbfTableHandler.insertAbfrage(selected);
abfragen.add(selected);
}
else {
UcmdbAbfTableHandler.updateAbfrage(selected);
}
PrimeFaces.current().executeScript("PF('manageQueriesDialog').hide()");
PrimeFaces.current().ajax().update("dt-queries");
}
public void startAbfrage(Abfrage abf) {
UcmdbAbfrageInteface.doRequest(abf);
}
public void deleteAbfrage() {
if(selected != null) {
UcmdbAbfTableHandler.deleteAbfrage(selected);
abfragen.remove(selected);
}
PrimeFaces.current().ajax().update("dt-queries");
}
public List<Abfrage> getAbfragen() { return abfragen; }
public Abfrage getSelected() { return selected; }
public RequestResolutions[] getRequestResolutions() { return requestResolutions; }
public void setSelected(Abfrage selected) { this.selected = selected; }
}
我已经包括了所有进口商品,因为可能有一个是假包裹。我的问题是,如果我点击新建,对话框将保持为空,因为他认为该对象是空的。当我点击编辑按钮时,对象被加载,但我无法保存它,因为 abfTyp 是空的(它是 required="true"),在我将 required 设置为 false 之后我可以保存,但我的对象有旧数据而不是我更改的日期。我有一个几乎相似的页面,它运行良好,但我找不到区别。 RequestResolutions 是一个愚蠢的 ENUM,没有任何功能。
使用“neu”时对话框为空,因为您每次都创建一个新版本的“selected”。旧数据重新出现在“编辑”中,因为上一次验证失败,但您立即关闭了对话框。然后你使用 p:resetInput
重置回存储的值。如果 selectList 值为空,这意味着来自数据源的内容与您提供的枚举 select 列表中的任何值都不匹配。
我在使示例正常工作时遇到了很多问题...缺少表格,更新=引用错误。但我认为主要的设计问题是您没有在对话框中显示任何验证错误 - 只是立即关闭对话框 window。顺便说一下,您应该主要在命令按钮上使用 action=
,而不是 actionListener=
。请参阅 here 了解原因。在执行操作方法之前,所有字段验证都将通过。
我建议修改如下:
<p:commandButton value="Neu" icon="pi pi-plus" action="#{abfrageHandler.newAbfrage}"
update=":ucmdbform:manage-queries-content"
oncomplete="PF('manageQueriesDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<!-- <p:resetInput target=":ucmdbform:manage-queries-content"/> -->
</p:commandButton>
.
.
<p:commandButton value="Speichern" icon="pi pi-check"
action="#{abfrageHandler.saveAbfrage}"
update=":ucmdbform:dt-queries :ucmdbform:manage-queries-content"
oncomplete="if ( args.saved == 1 ) { PF('manageQueriesDialog').hide()};"/>
加上所有 actionListeners="..."
--> action="..."
;加上 p:message
到所有可能验证失败的对话框字段。
public void saveAbfrage() {
if (selected.getPk() == null) {
selected.setPk(UUID.randomUUID());
UcmdbAbfTableHandler.insertAbfrage(selected);
abfragen.add(selected);
} else {
UcmdbAbfTableHandler.updateAbfrage(selected);
}
PrimeFaces.current().ajax().addCallbackParam("saved", 1);
// PrimeFaces.current().ajax().update(":ucmdbform:dt-queries");
// PrimeFaces.current().executeScript("PF('manageQueriesDialog').hide();");
}
我遇到了以下问题。我有一个 XHTML:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
template="../layout.xhtml">
<ui:define name="header">
<div id="header">
Abfragen
</div>
</ui:define>
<ui:define name="main">
<p:toolbar>
<p:toolbarGroup>
<p:commandButton value="Neu" icon="pi pi-plus" actionListener="#{abfrageHandler.newAbfrage}"
update="manage-queries-content" oncomplete="PF('manageQueriesDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<p:resetInput target=":ucmdbform:ucmdbtab:manage-ucmdb-queries-content"/>
</p:commandButton>
</p:toolbarGroup>
</p:toolbar>
<p:dataTable id="dt-queries" widgetVar="dtQueries" reflow="true" showGridlines="true" size="small"
var="querie" value="#{abfrageHandler.abfragen}">
<p:column headerText="Abfrage">
<h:outputText value="#{querie.name}" />
</p:column>
<p:column headerText="TQL">
<h:outputText value="#{querie.tql}" />
</p:column>
<p:column headerText="Zyklus">
<h:outputText value="#{querie.zyklus}" />
</p:column>
<p:column headerText="Typ">
<h:outputText value="#{querie.typ}" />
</p:column>
<p:column exportable="false">
<p:commandButton icon="pi pi-pencil" update="manage-queries-content"
oncomplete="PF('manageQueriesDialog').show()"
styleClass="edit-button rounded-button ui-button-success" process="@this">
<f:setPropertyActionListener value="#{querie}" target="#{abfrageHandler.selected}"/>
<p:resetInput target="manage-queries-content"/>
</p:commandButton>
<p:commandButton icon="pi pi-search" actionListener="#{abfrageHandler.startAbfrage(querie)}"
styleClass="edit-button rounded-button ui-button-success" process="@this">
</p:commandButton>
<p:commandButton class="ui-button-warning rounded-button" icon="pi pi-trash" process="@this"
oncomplete="PF('deleteQuerieDialog').show()">
<f:setPropertyActionListener value="#{querie}" target="#{abfrageHandler.selected}"/>
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Abfrage" showEffect="fade" modal="true" width="600px"
widgetVar="manageQueriesDialog" responsive="true">
<p:outputPanel id="manage-queries-content" class="ui-fluid">
<p:outputPanel rendered="#{not empty abfrageHandler.selected}">
<div class="p-field">
<p:outputLabel for="abfName">Name</p:outputLabel>
<p:inputText id="abfName" value="#{abfrageHandler.selected.name}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="abfTql">TQL</p:outputLabel>
<p:inputText id="abfTql" value="#{abfrageHandler.selected.tql}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="abfZyklus">Zyklus</p:outputLabel>
<p:inputText id="abfZyklus" value="#{abfrageHandler.selected.zyklus}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="@next">Abfrageart</p:outputLabel>
<p:selectOneMenu id="abfTyp" value="#{abfrageHandler.selected.typ}" required="false">
<f:selectItem itemLabel="Eins wählen" itemValue=""/>
<f:selectItems value="#{abfrageHandler.requestResolutions}" var="reso"
itemLabel="#{reso.toString()}" itemValue="#{reso}"/>
</p:selectOneMenu>
</div>
</p:outputPanel>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Speichern" icon="pi pi-check" actionListener="#{abfrageHandler.saveAbfrage}"
update="manage-queries-content" process="manage-queries-content @this"/>
<p:commandButton value="Abbruch" icon="pi pi-times" onclick="PF('manageQueriesDialog').hide()"
class="ui-button-secondary"/>
</f:facet>
</p:dialog>
<p:confirmDialog widgetVar="deleteQuerieDialog" showEffect="fade" width="300"
message="TQL wirklich löschen?" header="Bestätigen" severity="warn">
<p:commandButton value="Ja" icon="pi pi-check" actionListener="#{abfrageHandler.deleteParameter}"
process="@this" oncomplete="PF('deleteQuerieDialog').hide()"/>
<p:commandButton value="Nein" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
onclick="PF('deleteQuerieDialog').hide()"/>
</p:confirmDialog>
</ui:define>
</ui:composition>
以及后端中的以下 bean:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.primefaces.PrimeFaces;
import main.java.ucmdbtool.RequestResolutions;
import main.java.ucmdbtool.UcmdbAbfrageInteface;
import main.java.ucmdbtool.table.Abfrage;
import main.java.ucmdbtool.table.UcmdbAbfTableHandler;
@SuppressWarnings("serial")
@Named("abfrageHandler")
@ViewScoped
public class AbfrageHandler implements Serializable {
private List<Abfrage> abfragen = new ArrayList<>();
private Abfrage selected;
private RequestResolutions[] requestResolutions;
@PostConstruct
private void init() {
abfragen = UcmdbAbfTableHandler.getAbfragen();
requestResolutions = RequestResolutions.values();
}
public void newAbfrage() {
selected = new Abfrage();
}
public void saveAbfrage() {
if (selected.getPk() == null) {
selected.setPk(UUID.randomUUID());
UcmdbAbfTableHandler.insertAbfrage(selected);
abfragen.add(selected);
}
else {
UcmdbAbfTableHandler.updateAbfrage(selected);
}
PrimeFaces.current().executeScript("PF('manageQueriesDialog').hide()");
PrimeFaces.current().ajax().update("dt-queries");
}
public void startAbfrage(Abfrage abf) {
UcmdbAbfrageInteface.doRequest(abf);
}
public void deleteAbfrage() {
if(selected != null) {
UcmdbAbfTableHandler.deleteAbfrage(selected);
abfragen.remove(selected);
}
PrimeFaces.current().ajax().update("dt-queries");
}
public List<Abfrage> getAbfragen() { return abfragen; }
public Abfrage getSelected() { return selected; }
public RequestResolutions[] getRequestResolutions() { return requestResolutions; }
public void setSelected(Abfrage selected) { this.selected = selected; }
}
我已经包括了所有进口商品,因为可能有一个是假包裹。我的问题是,如果我点击新建,对话框将保持为空,因为他认为该对象是空的。当我点击编辑按钮时,对象被加载,但我无法保存它,因为 abfTyp 是空的(它是 required="true"),在我将 required 设置为 false 之后我可以保存,但我的对象有旧数据而不是我更改的日期。我有一个几乎相似的页面,它运行良好,但我找不到区别。 RequestResolutions 是一个愚蠢的 ENUM,没有任何功能。
使用“neu”时对话框为空,因为您每次都创建一个新版本的“selected”。旧数据重新出现在“编辑”中,因为上一次验证失败,但您立即关闭了对话框。然后你使用 p:resetInput
重置回存储的值。如果 selectList 值为空,这意味着来自数据源的内容与您提供的枚举 select 列表中的任何值都不匹配。
我在使示例正常工作时遇到了很多问题...缺少表格,更新=引用错误。但我认为主要的设计问题是您没有在对话框中显示任何验证错误 - 只是立即关闭对话框 window。顺便说一下,您应该主要在命令按钮上使用 action=
,而不是 actionListener=
。请参阅 here 了解原因。在执行操作方法之前,所有字段验证都将通过。
我建议修改如下:
<p:commandButton value="Neu" icon="pi pi-plus" action="#{abfrageHandler.newAbfrage}"
update=":ucmdbform:manage-queries-content"
oncomplete="PF('manageQueriesDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<!-- <p:resetInput target=":ucmdbform:manage-queries-content"/> -->
</p:commandButton>
.
.
<p:commandButton value="Speichern" icon="pi pi-check"
action="#{abfrageHandler.saveAbfrage}"
update=":ucmdbform:dt-queries :ucmdbform:manage-queries-content"
oncomplete="if ( args.saved == 1 ) { PF('manageQueriesDialog').hide()};"/>
加上所有 actionListeners="..."
--> action="..."
;加上 p:message
到所有可能验证失败的对话框字段。
public void saveAbfrage() {
if (selected.getPk() == null) {
selected.setPk(UUID.randomUUID());
UcmdbAbfTableHandler.insertAbfrage(selected);
abfragen.add(selected);
} else {
UcmdbAbfTableHandler.updateAbfrage(selected);
}
PrimeFaces.current().ajax().addCallbackParam("saved", 1);
// PrimeFaces.current().ajax().update(":ucmdbform:dt-queries");
// PrimeFaces.current().executeScript("PF('manageQueriesDialog').hide();");
}