Java Platform, Enterprise Edition (Java EE) 8 The Java EE Tutorial

## HTML5-Friendly Markup

When you want to produce user interface features for which HTML does not have its own elements, you can create a custom JavaServer Faces component and insert it in your Facelets page. This mechanism can cause a simple element to create complex web code. However, creating such a component is a significant task (see Chapter 15, "Creating Custom UI Components and Other Custom Objects").

HTML5 offers new elements and attributes that can make it unnecessary to write your own components. It also provides many new capabilities for existing components. JavaServer Faces technology supports HTML5 not by introducing new UI components that imitate HTML5 ones but by allowing you to use HTML5 markup directly. It also allows you to use JavaServer Faces attributes within HTML5 elements. JavaServer Faces technology support for HTML5 falls into two categories:

- Pass-through elements

- Pass-through attributes

The effect of the HTML5-friendly markup feature is to offer the Facelets page author almost complete control over the rendered page output, rather than having to pass this control off to component authors. You can mix and match JavaServer Faces and HTML5 components and elements as you see fit.

### Using Pass-Through Elements

Pass-through elements allow you to use HTML5 tags and attributes but to treat them as equivalent to JavaServer Faces components associated with a server-side `UIComponent` instance.

To make an element that is not a JavaServer Faces element a pass-through element, specify at least one of its attributes using the `http://xmlns.jcp.org/jsf` namespace. For example, the following code declares the namespace with the short name `jsf`:

    <html ... xmlns:jsf="http://xmlns.jcp.org/jsf"
    ...
        <input type="email" jsf:id="email" name="email"
               value="#{reservationBean.email}" required="required"/>

Here, the `jsf` prefix is placed on the `id` attribute so that the HTML5 input tag’s attributes are treated as part of the Facelets page. This means that, for example, you can use EL expressions to retrieve managed bean properties.

Table 8-4 shows how pass-through elements are rendered as Facelets tags. The JSF implementation uses the element name and the identifying attribute to determine the corresponding Facelets tag that will be used in the server-side processing. The browser, however, interprets the markup that the page author has written.

Table 8-4 How Facelets Renders HTML5 Elements

HTML5 Element Name | Identifying Attribute | Facelets Tag
`a` | `jsf:action` | `h:commandLink`
`a` | `jsf:actionListener` | `h:commandLink`
`a` | `jsf:value` | `h:outputLink`
`a` | `jsf:outcome` | `h:link`
`body` | + | `h:body`
`button` | + | `h:commandButton`
`button` | `jsf:outcome` | `h:button`
`form` | + | `h:form`
`head` | + | `h:head`
`img` | + | `h:graphicImage`
`input` | `type="button"` | `h:commandButton`
`input` | `type="checkbox"` | `h:selectBooleanCheckbox`
`input` | `type="color"` | `h:inputText`
`input` | `type="date"` | `h:inputText`
`input` | `type="datetime"` | `h:inputText`
`input` | `type="datetime-local"` | `h:inputText`
`input` | `type="email"` | `h:inputText`
`input` | `type="month"` | `h:inputText`
`input` | `type="number"` | `h:inputText`
`input` | `type="range"` | `h:inputText`
`input` | `type="search"` | `h:inputText`
`input` | `type="time"` | `h:inputText`
`input` | `type="url"` | `h:inputText`
`input` | `type="week"` | `h:inputText`
`input` | `type="file"` | `h:inputFile`
`input` | `type="hidden"` | `h:inputHidden`
`input` | `type="password"` | `h:inputSecret`
`input` | `type="reset"` | `h:commandButton`
`input` | `type="submit"` | `h:commandButton`
`input` | `type="*"` | `h:inputText`
`label` | + | `h:outputLabel`
`link` | + | `h:outputStylesheet`
`script` | + | `h:outputScript`
`select` | `multiple="*"` | `h:selectManyListbox`
`select` | + | `h:selectOneListbox`
`textarea` | + | `h:inputTextArea`

### Using Pass-Through Attributes

Pass-through attributes are the converse of pass-through elements. They allow you to pass attributes that are not JavaServer Faces attributes through to the browser without interpretation. If you specify a pass-through attribute in a JavaServer Faces `UIComponent`, the attribute name and value are passed straight through to the browser without being interpreted by JavaServer Faces components or renderers. There are several ways to specify pass-through attributes.

- Use the JavaServer Faces namespace for pass-through attributes to prefix the attribute names within a JavaServer Faces component. For example, the following code declares the namespace with the short name `p`, then passes the `type`, `min`, `max`, `required`, and `title` attributes through to the HTML5 `input` component:

      <html ... xmlns:p="http://xmlns.jcp.org/jsf/passthrough"
      ...

      <h:form prependId="false">
      <h:inputText id="nights" p:type="number" value="#{bean.nights}"
                   p:min="1" p:max="30" p:required="required"
                   p:title="Enter a number between 1 and 30 inclusive.">
              ...

  This will cause the following markup to be rendered (assuming that `bean.nights` has a default value set to 1):

      <input id="nights" type="number" value="1" min="1" max="30"
             required="required"
             title="Enter a number between 1 and 30 inclusive.">

- To pass a single attribute, nest the `f:passThroughAttribute` tag within a component tag. For example:

      <h:inputText value="#{user.email}">
          <f:passThroughAttribute name="type" value="email" />
      </h:inputText>

  This code would be rendered similarly to the following:

      <input value="me@me.com" type="email" />

- To pass a group of attributes, nest the `f:passThroughAttributes` tag within a component tag, specifying an EL value that must evaluate to a `Map<String, Object>`. For example:

      <h:inputText value="#{bean.nights">
          <f:passThroughAttributes value="#{bean.nameValuePairs}" />
      </h:inputText>

  If the bean used the following `Map` declaration and initialized the map in the constructor as follows, the markup would be similar to the output of the code that uses the pass-through attribute namespace:

      private Map<String, Object> nameValuePairs;
      ...
      public Bean() {
          this.nameValuePairs = new HashMap<>();
          this.nameValuePairs.put("type", "number");
          this.nameValuePairs.put("min", "1");
          this.nameValuePairs.put("max", "30");
          this.nameValuePairs.put("required", "required");
          this.nameValuePairs.put("title",
                  "Enter a number between 1 and 4 inclusive.");
      }

### The reservation Example Application

The `reservation` example application provides a set of HTML5 `input` elements of various types to simulate purchasing tickets for a theatrical event. It consists of two Facelets pages, `reservation.xhtml` and `confirmation.xhtml`, and a backing bean, `ReservationBean.java`. The pages use both pass-through attributes and pass-through elements.

The source code for this application is in the tut-install`/examples/web/jsf/reservation/` directory.

The following topics are addressed here:

- The Facelets Pages for the reservation Application

- The Managed Bean for the reservation Application

- To Build, Package, and Deploy the reservation Example Using NetBeans IDE

#### The Facelets Pages for the reservation Application

The first important feature of the Facelets pages for the `reservation` application is the `DOCTYPE` header. Most Facelets pages in JavaServer Faces applications refer to the XHTML DTD. The facelets pages for this application begin simply with the following `DOCTYPE` header, which indicates an HTML5 page:

    <!DOCTYPE html>

The namespace declarations in the `html` element of the `reservation.xhtml` page specify both the `jsf` and the `passthrough` namespaces:

    <html lang="en"
          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://xmlns.jcp.org/jsf/passthrough"
          xmlns:jsf="http://xmlns.jcp.org/jsf">

Next, an empty `h:head` tag followed by an `h:outputStylesheet` tag within the `h:body` tag illustrates the use of a relocatable resource (as described in Relocatable Resources):

    <h:head>
    </h:head>
    <h:body>
        <h:outputStylesheet name="css/stylesheet.css" target="head"/>

The `reservation.xhtml` page uses pass-through elements for most of the form fields on the page. This allows it to use some HTML5-specific `input` element types, such as `date` and `email`. For example, the following element renders both a date format and a calendar from which you can choose a date. The `jsf` prefix on the `id` attribute makes the element a pass-through one:

        <input type="date" jsf:id="date" name="date"
               value="#{reservationBean.date}" required="required"
               title="Enter or choose a date."/>

The field for the number of tickets, however, uses the `h:passThroughAttributes` tag to pass a `Map` defined in the managed bean. It also recalculates the total in response to a change in the field:

        <h:inputText id="tickets" value="#{reservationBean.tickets}">
            <f:passThroughAttributes value="#{reservationBean.ticketAttrs}"/>
            <f:ajax event="change" render="total"
                    listener="#{reservationBean.calculateTotal}"/>
        </h:inputText>

The field for the price specifies the `number` type as a pass-through attribute of the `h:inputText` element, offering a range of four ticket prices. Here, the `p` prefix on the HTML5 attributes passes them through to the browser uninterpreted by the JavaServer Faces input component:

        <h:inputText id="price" p:type="number"
                     value="#{reservationBean.price}"
                     p:min="80" p:max="120"
                     p:step="20" p:required="required"
                     p:title="Enter a price: 80, 100, 120, or 140.">
            <f:ajax event="change" render="total"
                    listener="#{reservationBean.calculateTotal}"/>
        </h:inputText>

The output of the `calculateTotal` method that is specified as the listener for the Ajax event is rendered in the output element whose `id` and `name` value is `total`. See Chapter 13, "Using Ajax with JavaServer Faces Technology", for more information.

The second Facelets page, `confirmation.xhtml`, uses a pass-through `output` element to display the values entered by the user and provides a Facelets `h:commandButton` tag to allow the user to return to the `reservation.xhtml` page.

#### The Managed Bean for the reservation Application

The session-scoped managed bean for the reservation application, `ReservationBean.java`, contains properties for all the elements on the Facelets pages. It also contains two methods, `calculateTotal` and `clear`, that act as listeners for Ajax events on the `reservation.xhtml` page.

#### To Build, Package, and Deploy the reservation Example Using NetBeans IDE

1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

2. From the File menu, choose Open Project.

3. In the Open Project dialog box, navigate to:

       tut-install/examples/web/jsf

4. Select the `reservation` folder.

5. Click Open Project.

6. In the Projects tab, right-click the `reservation` project and select Build.

   This option builds the example application and deploys it to your GlassFish Server instance.

#### To Build, Package, and Deploy the reservation Example Using Maven

1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

2. In a terminal window, go to:

       tut-install/examples/web/jsf/reservation/

3. Enter the following command:

       mvn install

   This command builds and packages the application into a WAR file, `reservation.war`, that is located in the `target` directory. It then deploys the WAR file to your GlassFish Server instance.

#### To Run the reservation Example

At the time of the publication of this tutorial, the browser that most fully implements HTML5 is Google Chrome, and it is recommended that you use it to run this example. Other browsers are catching up, however, and may work equally well by the time you read this.

1. Enter the following URL in your web browser:

       http://localhost:8080/reservation

2. Enter information in the fields of the `reservation.xhtml` page.

   The Performance Date field has a date field with up and down arrows that allow you to increment and decrement the month, day, and year as well as a larger down arrow that brings up a date editor in calendar form.

   The Number of Tickets and Ticket Price fields also have up and down arrows that allow you to increment and decrement the values within the allowed range and steps. The Estimated Total changes when you change either of these two fields.

   Email addresses and dates are checked for format, but not for validity (you can make a reservation for a past date, for instance).

3. Click Make Reservation to complete the reservation or Clear to restore the fields to their default values.

4. If you click Make Reservation, the `confirmation.xhtml` page appears, displaying the submitted values.

   Click Back to return to the `reservation.xhtml` page.

Copyright © 2017, Oracle and/or its affiliates. All rights reserved.