PrimeFaces:在动态生成的对话框中打开外部页面
我已经在即将出版的PrimeFaces Cookbook 2版中写了一篇关于食谱的博客。 在这篇文章中,我想发表第二篇关于一个名为Dialog Framework
的小型框架的文章。 我个人喜欢它,因为我记得我为使用Struts框架付出同样的努力而付出的代价。 当您想将外部页面加载到弹出窗口中并向该页面提交一些数据时,您必须使用隐藏表单调用window.open
,将传递的值设置为隐藏字段,通过JavaScript将表单提交给外部页面,然后等到该页面已准备好在window.onload
或document.ready
。 很多繁琐的工作。 PrimeFaces可以为您完成这项工作,此外, p:dialog
还提供了漂亮的用户界面来替代弹出窗口。
PrimeFaces对话框的常规用法是使用p:dialog
的声明方法。 除了这种声明式方法之外,还有一种编程方法。 编程方法基于编程API,其中在运行时创建和销毁对话框。 它称为Dialog Framework
。 对话框框架用于在动态生成的对话框中打开外部页面。 用法很简单, RequestContext
提供两个方法: openDialog
和closeDialog
允许打开和关闭动态对话框。 此外,对话框架使将数据从对话中显示的页面传回至调用者页面成为可能。
在本食谱中,我们将演示Dialog Framework中可用的所有功能。 我们将以编程方式打开一个带有选项的对话框,并将参数传递给该对话框中显示的页面。 我们还将满足在源(调用方)页面和对话框之间进行通信的可能性。
做好准备
Dialog Framework在faces-config.xml
需要以下配置:
<application> <action-listener>org.primefaces.application.DialogActionListener</action-listener> <navigation-handler>org.primefaces.application.DialogNavigationHandler</navigation-handler> <view-handler>org.primefaces.application.DialogViewHandler</view-handler> </application>
怎么做…
我们将开发一个带有单选按钮的页面,以选择一本可用的PrimeFaces图书进行评级。 单击按钮“ Rate the selected book
后,评分本身将在对话框中发生。
屏幕快照的XHTML代码段在下面列出。
<p:messages id="messages" showSummary="true" showDetail="false"/> <p:selectOneRadio id="books" layout="pageDirection" value="#{dialogFrameworkBean.bookName}"> <f:selectItem itemLabel="PrimeFaces Cookbook" itemValue="PrimeFaces Cookbook"/> <f:selectItem itemLabel="PrimeFaces Starter" itemValue="PrimeFaces Starter"/> <f:selectItem itemLabel="PrimeFaces Beginner's Guide" itemValue="PrimeFaces Beginner's Guide"/> <f:selectItem itemLabel="PrimeFaces Blueprints" itemValue="PrimeFaces Blueprints"/> </p:selectOneRadio> <p:commandButton value="Rate the selected book" process="@this books" actionListener="#{dialogFrameworkBean.showRatingDialog}" style="margin-top: 15px"> <p:ajax event="dialogReturn" update="messages" listener="#{dialogFrameworkBean.onDialogReturn}"/> </p:commandButton>
对话框中的页面是整页bookRating.xhtml
其中包含Rating组件p:rating
。 它还显示选择进行评级的书的名称。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://primefaces.org/ui"> <f:view contentType="text/html" locale="en"> <f:metadata> <f:viewParam name="bookName" value="#{bookRatingBean.bookName}"/> </f:metadata> <h:head> <title>Rate the book!</title> </h:head> <h:body> <h:form> What is your rating for the book <strong>#{bookRatingBean.bookName}</strong>? <p/> <p:rating id="rating"> <p:ajax event="rate" listener="#{bookRatingBean.onrate}"/> <p:ajax event="cancel" listener="#{bookRatingBean.oncancel}"/> </p:rating> </h:form> </h:body> </f:view> </html>
下一个屏幕截图演示了对话框的外观。
单击等级星级或取消符号将关闭对话框。 源(呼叫者)页面显示一条消息,其中所选的评级值在0到5之间。
最有趣的部分是bean中的逻辑。 豆DialogFrameworkBean
通过调用方法打开的对话框中的等级页面openDialog()
与结果,选项和POST参数上RequestContext
实例。 此外,bean定义了一个AJAX侦听器onDialogReturn()
,当对话框关闭后从对话框返回数据(选定的评级)时,将调用该侦听onDialogReturn()
。
@Named @ViewScoped public class DialogFrameworkBean implements Serializable { private String bookName; public void showRatingDialog() { Map<String, Object> options = new HashMap<String, Object>(); options.put("modal", true); options.put("draggable", false); options.put("resizable", false); options.put("contentWidth", 500); options.put("contentHeight", 100); options.put("includeViewParams", true); Map<String, List<String>> params = new HashMap<String, List<String>>(); List<String> values = new ArrayList<String>(); values.add(bookName); params.put("bookName", values); RequestContext.getCurrentInstance().openDialog("/views/chapter11/bookRating", options, params); } public void onDialogReturn(SelectEvent event) { Object rating = event.getObject(); FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "You rated the book with " + rating, null); FacesContext.getCurrentInstance().addMessage(null, message); } // getters / setters ... }
Bean BookRatingBean
为Rating component
定义了两个侦听器。 当用户分别单击星号和取消符号时,将调用它们。 我们呼吁有closeDialog()
上RequestContext
实例来触发对话框关闭和额定电流值传递给听众提到onDialogReturn()
@Named @RequestScoped public class BookRatingBean { private String bookName; public void onrate(RateEvent rateEvent) { RequestContext.getCurrentInstance().closeDialog(rateEvent.getRating()); } public void oncancel() { RequestContext.getCurrentInstance().closeDialog(0); } // getters / setters ... }
怎么运行的…
RequestContext
提供了两个同名openDialog
方法,可在运行时动态打开对话框。 第一个只有一个参数–用于解决导航案例的逻辑结果。 第二个参数包含三个参数-结果,对话框的配置选项和发送到对话框中显示的视图的参数。 在示例中,我们使用了第二个变体。 选项作为键值对放入Map
中。 参数也放入Map
。 在我们的案例中,我们输入所选书籍的名称。 之后,通过f:viewParam
在对话框页面bookRating.xhtml
接收该名称。 f:viewParam
将传输的参数设置到BookRatingBean
,以便在Rating
组件上方的标题中可用。
提示:请参阅《 PrimeFaces用户指南》以查看支持的对话框的配置选项的完整列表。
让我们经历一下请求-响应生命周期。 一旦收到由命令按钮引起的请求响应,便会创建一个对话框,其中包含iframe
。 iframe
的URL指向整页,在本例中为bookRating.xhtml
。 该页面将向下流并显示在对话框中。 如您所见,总是有两个请求:第一个初始POST和第二个GET由iframe发送。 请注意,对话框框架仅适用于初始AJAX请求。 非AJAX请求将被忽略。 另请注意,对话框的标题取自HTML title
元素。
正如我们上面已经提到,这个对话框可以通过编程关闭invoking
该方法closeDialog
上RequestContext
实例。 在调用者页面上,触发对话框的按钮需要具有一个dialogReturn
事件的AJAX侦听器,以便能够从对话框接收任何数据。 数据作为参数传递给方法closeDialog(Object data)
。 在示例中,我们传递了一个正整数值rateEvent.getRating()
或0
。