The regular usage of PrimeFaces' dialog is a declarative approach with p:dialog
. Besides this declarative approach, there is a programmatic approach as well. The programmatic approach is based on a programmatic API where dialogs are created and destroyed at runtime. It is called Dialog Framework. Dialog Framework is used to open external pages in dynamically generated dialogs. The usage is quite simple; RequestContext
provides two methods—openDialog
and closeDialog
—that allow the opening and closing of dynamic dialogs. Furthermore, Dialog Framework makes it possible to pass data back from the page displayed in the dialog to the caller page.
In this recipe, we will demonstrate all features available in Dialog Framework. We will open a dialog with options programmatically and pass parameters to the page displayed in this dialog. We will also meet the possibility of communicating between the source (caller) page and the dialog.
Dialog Framework requires the following configuration in 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>
We will develop a page with radio buttons to select an available PrimeFaces' book for rating as follows. The rating itself happens in a dialog after a click on the Rate the selected book button.
The XHTML snippet for the preceding screenshot is shown here:
<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>
The page in the dialog is a full bookRating.xhtml
page with a rating
component, p:rating
. It also shows the name of the book selected for rating. Here's the code to obtain the desired results:
<!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>
The next screenshot demonstrates how the dialog looks:
A click on a rating star or the cancel symbol closes the dialog. The source (caller) page displays a message with the selected rating value in the range 0–5:
The most interesting part is the logic in beans. The DialogFrameworkBean
bean opens the rating page within the dialog by invoking the openDialog()
method with the outcome, options, and POST parameters on a RequestContext
instance. Furthermore, the bean defines the onDialogReturn()
AJAX listener, which is invoked when the data (selected rating) is returned from the dialog after it was closed. The following code encapsulates this discussion:
@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 ... }
The BookRatingBean
bean defines two listeners for the rating
component. They are invoked when the user clicks on a star and the cancel symbol, respectively. We call closeDialog()
on a RequestContext
instance to trigger dialog closing and to pass the current rating value to the onDialogReturn()
listener:
@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
provides two methods of the same name, openDialog
, to open a dialog dynamically at runtime. The first one only has one parameter—the logical outcome used to resolve a navigation case. The second one has three parameters—outcome, dialog configuration options, and parameters that are sent to the view displayed in the dialog. We used the second variant in the example. The options are put into Map
as key-value pairs. The parameters are put into Map
too. In our case, we put the name of the selected book. After that, the name is received in the dialog's bookRating.xhtml
page via the f:viewParam
. The transferred parameter is set into BookRatingBean
by f:viewParam
so that it is available in the heading above the Rating
component.
Refer to the PrimeFaces User's Guide (http://primefaces.org/documentation.html) to see a full list of the supported dialog's configuration options.
Let's go through the request-response life cycle. Once the response is received from the request caused by the command button, a dialog gets created with an iframe
tag inside. The URL of iframe
points to the full page, which, in our case, is bookRating.xhtml
. The page will be streamed down and shown in the dialog. As you can see, there are always two requests: the initial POST and the second GET sent by iframe
. Note that Dialog Framework only works with initial AJAX requests. Non-AJAX requests are ignored.
As mentioned earlier, the dialog can be closed programmatically by invoking the closeDialog
method on a RequestContext
instance. On the caller page, the button that triggers the dialog needs to have an AJAX listener for the dialogReturn
event to be able to receive any data from the dialog. The data is passed as a parameter to the closeDialog(Object data)
method. In the example, we pass either a positive integer value rateEvent.getRating()
or 0
.
Dialog Framework also provides a convenient way to display FacesMessage
in a dynamically generated dialog. This can be achieved by invoking the showMessageInDialog(FacesMessage message)
method on a RequestContext
instance.
Refer to PrimeFaces User's Guide (http://primefaces.org/documentation.html) and the Dialog Framework chapter to see how displaying messages in a dialog works.
This recipe is available in the demo web application on GitHub (https://github.com/ova2/primefaces-cookbook/tree/second-edition). Clone the project if you have not done it yet, explore the project structure, and build and deploy the WAR file on application servers compatible with Servlet 3.x, such as JBoss WildFly and Apache TomEE.
The showcase for the recipe is available at http://localhost:8080/pf-cookbook/views/chapter11/dialogFramework.jsf
.
3.21.159.82