打开位于另一个.xhtml文件中的PrimeFaces对话框



我有许多相互关联的问题,因此问题的标题可能不合适。对此感到抱歉。

我想在p:dialog中有一个p:inputTextp:commandButton,以便当用户按下该按钮或按回车键时,在p:inputText将保存在数据库中。为此,我 http://www.primefaces.org/showcase/ui/dialogForm.jsf 按照此示例进行操作,当我在单独的.xhtml文件中尝试它时,它工作正常,其中没有其他对话框或命令按钮。

<h:body>
<h:form id="form"> 
<p:commandButton id="showDialogButton" type="button" value="Show" onclick="PF('dlg').show()" />  
<p:dialog header="Enter FirstName" widgetVar="dlg" resizable="false">  

<h:panelGrid columns="2" style="margin-bottom:10px">  
<h:outputLabel for="firstname" value="Firstname:" />  
<p:inputText id="firstname" value="#{subjectController.attributeValue}" />  
</h:panelGrid>  
<p:commandButton id="submitButton" value="Submit" update=":form:display :form:firstname" action="#{subjectController.saveUpdateSubjectAttributeValue}" oncomplete="PF('dlg').hide();"/>  
<p:defaultCommand target="submitButton"></p:defaultCommand> 
</p:dialog>  
<p:outputPanel id="display" style="display:block;margin-top:10px;">  
<h:outputText id="name" value="Hello #{subjectController.attributeValue}" rendered="#{not empty subjectController.attributeValue}"/>  
</p:outputPanel>
</h:form>
</h:body>

我最初拥有的.xhtml文件包含许多其他对话框和命令按钮。当我在该文件中使用相同的代码时,它无法正常工作。通过无法正常工作,我的意思是说,当按下回车键或提交按钮时,用户输入的值不会在托管 Bean 中输入文本的相应设置器中设置。要在按回车键或按钮之前调用设置器,我需要在标签中使用p:ajaxp:inputText。我尝试使用p:ajax事件,例如"mouseout","blur","change"等。它们适用于提交按钮,但不适用于回车键。然后我尝试了"keypress"和"keyup"等。它们对两者都有效,但每次按下键时都会调用p:inputText值的设置器,这是不需要的。

我的第一个问题:

如果示例代码在单独的文件中工作正常,为什么当我在同一文件中有其他对话框或命令按钮时它不起作用。在这两种情况下,我都使用相同的托管 bean。有什么区别?

假设问题可能是在同一文件中使用多个对话框引起的,我想在单独的文件中声明这些对话框,以便我有A.xhtmlB.xhtmlC.xhtml包含实际内容的页面,每当我需要打开对话框时,所需的对话框都位于文件(例如dialog.xhtml)。作为JSF,Primefaces和Ajax的初学者,我对如何做到这一点感到困惑。在互联网上搜索我发现这篇文章相关的 PrimeFaces 对话框延迟加载(动态="true")不起作用?.但在这种情况下,p:dialog位于同一页面上,但此对话框中包含的内容位于另一个文件中,该文件使用ui:include包含在内。我试过这个,但它显示了相同的行为。

我的第二个问题:有没有办法以编程方式从另一个文件打开对话框,例如,如果我在A.xhtml中有一个p:commandButton并且p:dialog在同一文件中,我可以使用

<p:commandButton id="submitButton" value="Submit" update=":form:display :form:firstname" action="#{subjectController.saveUpdateSubjectAttributeValue}" oncomplete="PF('dlg').hide();"/>  

在相应的主题中,我有

saveUpdateSubjectAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance(); 
context.openDialog("openDialog");
// or 
context.execute("openDialog");
}

但是如果"openDialog"位于B.xhtml呢?

据我了解,我可以在ui:composition中使用封闭p:dialog(B.xhtml),并在A.xhtml中使用ui:include。但是我对如何以及在哪里称呼openDialog.open()openDialog.hide()感到困惑?

我试图复制您在此处发布的行为,我相信原因可能是 Yipitalp 提到的其他地方。

无论如何,以下是我使用的示例代码,它们可能会达到您的期望(Primefaces 4):

托管豆

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.primefaces.context.RequestContext;
@ManagedBean
@ViewScoped
public class DialogBean implements Serializable {
private String attribute1;
private String attribute2;
private String attribute3;
private String dlg;
public void openDialog() {
RequestContext context = RequestContext.getCurrentInstance();
context.execute("PF('" + dlg + "').show()");
}
public String getAttribute1() {
return attribute1;
}
public void setAttribute1(String attribute1) {
this.attribute1 = attribute1;
}
public String getAttribute2() {
return attribute2;
}
public void setAttribute2(String attribute2) {
this.attribute2 = attribute2;
}
public String getAttribute3() {
return attribute3;
}
public void setAttribute3(String attribute3) {
this.attribute3 = attribute3;
}
public String getDlg() {
return dlg;
}
public void setDlg(String dlg) {
this.dlg = dlg;
}
}

视图

请注意,我对视图中的每个对话框使用不同的窗体。

<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">  
<h:outputLabel for="dlg" value="Dlg:" />  
<p:selectOneMenu id="dlg" value="#{dialogBean.dlg}" >
<f:selectItem itemLabel="dlg1" itemValue="dlg1" />
<f:selectItem itemLabel="dlg2" itemValue="dlg2" />
<f:selectItem itemLabel="dlg3" itemValue="dlg3" />
</p:selectOneMenu>
</h:panelGrid>  
<p:commandButton id="submitButton" value="Submit" action="#{dialogBean.openDialog}"/>  
<p:defaultCommand target="submitButton" />
</h:form>

<p:button id="showDialogButton1" value="Show 1" onclick="PF('dlg1').show();
return false;" />
<p:button id="showDialogButton2" value="Show 2" onclick="PF('dlg2').show();
return false;" />
<p:button id="showDialogButton3" value="Show 3" onclick="PF('dlg3').show();
return false;" />
<br />
<p:dialog header="Enter FirstName" widgetVar="dlg1" resizable="false">  
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">  
<h:outputLabel for="firstname" value="Firstname:" />  
<p:inputText id="firstname" value="#{dialogBean.attribute1}" />  
</h:panelGrid>  
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg1').hide();"/>  
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:dialog header="Enter FirstName" widgetVar="dlg2" resizable="false">  
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">  
<h:outputLabel for="firstname" value="Firstname:" />  
<p:inputText id="firstname" value="#{dialogBean.attribute2}" />  
</h:panelGrid>  
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg2').hide();"/>  
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:dialog header="Enter FirstName" widgetVar="dlg3" resizable="false">  
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">  
<h:outputLabel for="firstname" value="Firstname:" />  
<p:inputText id="firstname" value="#{dialogBean.attribute3}" />  
</h:panelGrid>  
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg3').hide();"/>  
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:outputPanel autoUpdate="true" style="border: 1px solid black; margin-top:10px;">
Value 1: 
<h:outputText id="v1" value="#{dialogBean.attribute1}" />
<br />
Value 2: 
<h:outputText id="v2" value="#{dialogBean.attribute2}" />
<br />
Value 3: 
<h:outputText id="v3" value="#{dialogBean.attribute3}" />
</p:outputPanel>

我希望这能给你一些线索!

我能够使用DialogFramework解决大部分问题。我有一个Menu.xhtml页面,它包含p:tieredMenup:layoutUnitposition="north"我使用它来选择要打开的页面。根据所选内容,带有position="center"p:layoutUnit包含该页面,使用ui:includeMenu.xhtml页面包含一个h:formh:body内部有id="form",其他所有内容都放在这个h:form内。根据选择的不同,<p:layoutUnit position="center">中可以包含许多页面。其中之一是Person.xhtml(包含包含在ui:composition内的所有内容)。它包含一个p:fieldsetp:fieldset里面有 3 个p:dataTable.在此p:fieldset之外,我为每个数据表中放置了 3 个p:contextMenu一个。在我放置的其中一个p:contextMenu里面

<p:menuitem value="Update" actionListener="#{controller.updateAttributeValue}"  />

和相应的函数包含

public void updateAttributeValue(){
System.out.println("update  attribute value");
RequestContext context = RequestContext.getCurrentInstance();  
context.openDialog("selectCar2");
this.attributeValue = null;
}

selectCar2.xhtml包含以下代码

<h:body>  
<h:form>
<h:panelGrid id="updateAttributeValuePanel" columns="2" style="margin-bottom:10px">  
<h:outputLabel value="Attribute Value " />
<p:inputText id="attributeValue" value="#{controller.attributeValue}" required="true" />
</h:panelGrid>  
<p:commandButton id="saveUpdateAttributeValue" value="Submit" actionListener="#{controller.saveUpdateAttributeValue}" 
/>  
<p:commandButton id="cancelUpdateAttributeValue" value="Cancel "
action="#{controller.cancelUpdateAttributeValue}"
/>
<p:defaultCommand target="saveUpdateAttributeValue" />
</h:form>
</h:body> 

对应的保存功能如下

public void  saveUpdateAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();  
System.out.println("this.attributevalue = " + this.attributeValue);
////save value in database 
this.attributeValue = null;
context.update(":form:resourceAttributeValueDataTable");
//also tried    context.update("resourceAttributeValueDataTable");
context.closeDialog(this.attributeValue); 
}
and 

public void  cancelUpdateAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();  
context.closeDialog(this.attributeValue);
System.out.println("cancel update attribute value");
this.attributeValue = null;
System.out.println("this.attributevalue  = " + this.attributeValue);
}

对话框将打开,值将成功保存在数据库中。现在唯一的问题是相应的数据表没有更新,我需要刷新页面才能看到更新的值。以前我的对话框也在p:fieldset外的同一页面中,我没有使用内部对话框h:form所以我正在更新数据表

<p:commandButton id="saveUpdateAttributeValue" value="Submit" actionListener="#{controller.saveUpdateAttributeValue}" 
update = ":form:attributeValueDataTable  "/>

但是现在它们在两个不同的文件和两种不同的形式中,所以我不确定在这种情况下如何更新?我尝试使用

context.update(":form:resourceAttributeValueDataTable");
//or    
context.update("resourceAttributeValueDataTable");

但数据表不会更新。任何帮助将不胜感激。