Opening external pages in dynamically generated dialogs

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.

Getting ready

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>

How to do it…

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.

How to do it…

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:

How to do it…

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:

How to do it…

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
  ...
}

How it works…

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.

Tip

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.

Note

The title of the dialog is taken from the HTML title element.

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.

There's more…

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.

Tip

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.

PrimeFaces Cookbook Showcase application

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.35.122