Skip to main content

Streamline JSF Development with These 3 Facelets Must-Knows

July 22, 2011

Facelets offers a powerful way to organize and streamline JSF development. When a cat is thrust into the air, it magically lands upright and safely on its feet. Sadly, this is not always the case with software especially when tinctured with aggressive timelines and insufficient requirements. Facelets is to JSF what the magic is to the cat and can help avoid a CAT-astrophe.

This article is organized as follows: first, decorators are introduced and the underused yet powerful ui:decorate feature is leveraged; next, a powerful custom validator is built, with relatively little code setup; the third section shows how to re-use related form fields and encapsulate complex cross field behavior using ui:include; the concluding section takes all of these concepts and weaves them together.

Leveraging ui:decorate

Just as there are many ways to skin a cat, Facelets ui:decorate affords a way to skin, well, just about anything you can find in a JSF page. Let's take, for instance, a form section container used to visually group form fields and see how to give it a bit of mojo.

Before we do that, let's introduce a simple example. Figure 1 shows a screen shot of the text "Hello Facelets!" wrapped in a decorator. The decorator wraps the text with a green background and a rounded green border.



Figure 1. Hello Facelets!

Listing 1 shows the code used to decorate the text.

Listing 1.  /WebContent/example/example1.xhtml
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
02                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">       
03      
04                     
05 <html xmlns="http://www.w3.org/1999/xhtml"
06 xmlns:ui="http://java.sun.com/jsf/facelets"
07 xmlns:f="http://java.sun.com/jsf/core"
08 xmlns:h="http://java.sun.com/jsf/html">
09
10 <body>
11 <h:form>
12   <ui:decorate template="/WEB-INF/widget/formDecorator.xhtml">
13 Hello Facelets!
14   </ui:decorate>
15
16 ...
17 </h:form>
18 </body>
19 </html>

The mojo is that it only took 2 lines to achieve this effect; lines 12 and 14. The content you want to decorate is sandwiched between
the and tags. The template attribute on line 12 refers to the file that is used to perform the decorating. Line 6 declares the Facelets namespace. In our example, we decorated the text "Hello Facelets!" but we could have just as easily have decorated form fields as seen in Figure 2. To do this, we would simply replace the text "Hello Facelets!" with a group of form fields.



Figure 2. Decorate a grouping of form fields.

Listing 2 shows formDecorator.xhtml, the template responsible for creating this effect. We'll refer to it as the decorator. Lines 9-33 represent the stylesheet. The stylesheet is entirely responsible for creating the green background and the rounded green border without any images. Even though there are no images, we could have just as easily have opted to decorate the form fields with a sophisticated image border. In fact, we could conceivable change the border at any time to an image with relatively no impact to the core code since the logic that performs the decorating is localized within the decorator. In other words, change the decorator and all that is decorated gets a new skin. The ui:insert on line 47 is where the action begins. Conceptually, you can think of the ui:insert as being replaced with the content inside the start and end ui:decorate tags of Listing 1.

Listing 2.  /WEB-INF/widget/formDecorator.xhtml
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
02                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03                     
04 <html xmlns="http://www.w3.org/1999/xhtml"
05       xmlns:ui="http://java.sun.com/jsf/facelets"
06       xmlns:f="http://java.sun.com/jsf/core"
07       xmlns:h="http://java.sun.com/jsf/html">          
08
09 <style>
10 .wrapper { width: auto; }
11 * { border-color: #9CE6AE; }
12 .wrapper * { background-color: #DCFAB9; }
13 .wrapper .horizontalEdge, .wrapper .curvedEdge1, .wrapper .curvedEdge2, .wrapper .verticalEdge{
14 font-size: 1px;
15 display: block;
16 height: 1px;
17 overflow: hidden;
18 }
19 .wrapper .curvedEdge1, .wrapper .curvedEdge2, .wrapper .verticalEdge{
20 border-width: 0px 1px 0px 1px;
21 border-style: solid; }
22 .wrapper .horizontalEdge {
23 border-style: solid;
24 border-width: 1px 0px 0px 0px;
25 margin: 0px 5px; }
26 .wrapper .curvedEdge1 { margin: 0px 3px; }
27 .wrapper .curvedEdge2 { margin: 0px 2px; }
28 .wrapper .verticalEdge { margin: 0px 1px; height:2px; }
29 .wrapper .content {
30 border-width: 0px 1px 0px 1px;
31 border-style: solid;
32 padding: 0px 5px; }
33 </style>
34
35
36 <table width="80%">
37 <tr>
38 <td>
39 <div class="wrapper">
40 <span>
41 <span class="horizontalEdge"></span>
42 <span class="curvedEdge1" ></span>
43 <span class="curvedEdge2" ></span>
44 <span class="verticalEdge" ></span>
45 </span>
46 <div class="content">
47 <ui:insert />
48 </div>
49 <span>
50 <span class="verticalEdge" ></span>
51 <span class="curvedEdge2" ></span>
52 <span class="curvedEdge1" ></span>
53 <span class="horizontalEdge" ></span>
54 </span>
55 </div>
56 </td>
57 </tr>
58 </table>
59 </html>

Not only is the ui:decorate great for adding skins to the form body, form sections, and so on, but it's also perfectly suited for widget creation. In this next example, we'll see how to use a RichFaces rich:modalPanel using decorate and, to make it more interesting, we'll experiment with passing in parameters. Even though the code example utilizes RichFaces, keep in mind that the intention is to introduce the concepts and plant the idea that decorators can be used for widget creation. Figure 3 shows a link which, when clicked, will open the modal panel.



Figure 3. Modal panel link.

The modal panel that opens will display instructions on where to find the secure id as seen in Figure 4.



Figure 4. Modal panel after the link has been clicked.

Listing 3 shows the code that will be decorated.

Listing 3.  /WebContent/example/example2.xhtml
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
02                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03
04 <html xmlns="http://www.w3.org/1999/xhtml"
05 xmlns:ui="http://java.sun.com/jsf/facelets"
06 xmlns:f="http://java.sun.com/jsf/core"
07 xmlns:h="http://java.sun.com/jsf/html">
08
09 <body>
10
11
12
13   <h:form>
14
15       <table>
16    <tr>
17 <td align="left">
18   <ui:decorate template="/WEB-INF/widget/modalPanel.xhtml">
19     <ui:param name="linkText" value="How do I find my credit card's secure id?"/>
20     <ui:param name="title" value="Credit Card Security Code"/>
21     <ui:param name="id" value="creditCard"/>
22       The security code is the four digit number shown
23                       above the credit card number on the right-hand.
24   </ui:decorate>
25 </td>
26    </tr>
27       </table>
28
29
30 ...
31   </h:form>
32
33 </body>
34 </html>

Line 18 is the name of the template that will perform the decorating. Lines 19, 20, and 21 are the parameters that are passed to the decorator.
We pass it 3 parameters. The linkText parameter on line 19 is used to display the link we saw in Figure 3.
The title parameter on line 20 will be displayed in the modal panel's title bar.
The id parameter on line 21 is the unique id. Let's talk about this last parameter a bit more.
Since every JSF component must have a unique id and our modal panel can appear multiple times on a page, the id attribute takes care of this constraint by allowing the id to be passed in from the calling code. Now the onus is on the calling code to make sure the id is unique which is how it should be.

Listing 4 shows the modal dialog template that performs the decorating.

Listing 4.  /WEB-INF/widget/modalPanel.xhtml 
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
02                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03 
04                
05 <f:subview xmlns="http://www.w3.org/1999/xhtml"
06       xmlns:ui="http://java.sun.com/jsf/facelets"
07       xmlns:h="http://java.sun.com/jsf/html"
08       xmlns:f="http://java.sun.com/jsf/core"
09       xmlns:rich="http://richfaces.org/rich">
10
11
12     <rich:modalPanel width="300" height="100"
13                      autosized="true" id="panel#{id}" >
14         <f:facet name="header">
15             <h:panelGroup>
16                 <h:outputText value="#{title}"></h:outputText>
17             </h:panelGroup>
18         </f:facet>
19         <f:facet name="controls">
20             <h:panelGroup>
21 <a onclick="Richfaces.hideModalPanel('panel#{id}');"
22 style="font-family:arial;cursor:hand;">X Close</a>
23             </h:panelGroup>
24         </f:facet>    
25
26
27 <div style="overflow-y:auto;">
28 <table>
29 <tr>
30 <td align="left">
31     <ui:insert />
32 </td>
33 </tr>
34 </table>
35
36 </div>
37     </rich:modalPanel>
38
39     <a onclick="Richfaces.showModalPanel('panel#{id}', {top:'20px', left:'20px', height:'100'});" >
40
41 <h:outputText value="#{linkText}"
42 style="font-family:arial;font-size:11pt;cursor:hand;"></h:outputText>
43     </a>
44 </f:subview>

Line 12 starts the rich:modalPanel and on line 13, its #{id} is going to be replaced with the id parameter being passed in.
In Listing 3 we passed in creditCard as the parameter value for the id, therefore, the modal panel id will become panelcreditCard ("panel" is prepended to "creditCard").
On line 16 the title parameter passed in, "Credit Card Security Code", displays in the titlebar of the modal panel.
Lines 21-22 indicate that when the "X Close" link is clicked, a call to the internal richfaces method hideModalPanel will be made.
On line 31, the ui:insert inserts the text that explains how to locate the credit card's secure id. Finally, lines 41-42 display the linkText.

The mechanics of opening and closing the modal dialog along with its look and feel are encapsulated within the modalPanel.xhtml. This is how we want it to be.

Simplifying Form Field Validation

JSF (version 1.2 and earlier) has a handful of built in validators that are somewhat limited in what they offer. This leaves most of the heavy lifting of custom validation to us. Not an insurmountable task but can be a little pesky and somewhat unwieldy. Fortunately, there's a simple solution that leverages Facelets and allows us to create a custom validator much in the parlance of JSF's validation but with a few mighty perks. For one, the code to setup the custom validator is a lot less complicated and involved. Secondly, the custom validator accepts any number of arguments to be passed to it. In turn, Facelets will take care of auto-magically wiring the individual attributes found in the JSF tag directly into the custom validator class's fields. It does this by matching the attribute name in the tag to the corresponding class's field name. To understand this better, let's look at some code snippets that use a regex custom validator. You may be wondering, what's the point of illustrating a regex validator when JSF 2.0 already supports one. The idea is, once you understand the concept, you can extend the idea and tailor it to your individual project needs. With that said, let's move onto our example. The form contains a credit card field. When a user enters a credit card number, we want the value to be validated once the submit button is clicked. If the value entered doesn't pass validation we want the form to display an error message. Our tag has 2 attributes, regex and errorMessage. Let's look at the following code snippet:

	<example:regexValidator 
regex="([A-Za-z0-9 ]{0,20})"
errorMessage="The credit card number is invalid." />

regex is the regular expression that the form field value must conform to. errorMessage will be the error message that displays when the credit card number entered doesn't pass the regex validation. So in our example, the custom validator will be passed 2 arguments.

Here's the java class code snippet for the custom validator:

	private String regex;
private String errorMessage;

You can see that the tag attributes and the field names are identical. regex will be passed ([A-Za-z0-9 ]{0,20}) and errorMessage will be passed "The credit card number is invalid".

To see how this is put together, let's look at Listing 5 which shows how the custom validator is used. Line 9 declares the regex validator's namespace. On lines 25-26 the custom validator is used to validate the credit card number using the 2 attributes.

Listing 5.  /WebContent /example/example3.xhtml
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
02                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03
04
05 <html xmlns="http://www.w3.org/1999/xhtml"
06 xmlns:ui="http://java.sun.com/jsf/facelets"
07 xmlns:f="http://java.sun.com/jsf/core"
08 xmlns:h="http://java.sun.com/jsf/html"
09 xmlns:example="http://example.regex">
10
11 <body>
12
13 <h:form>
14 <table>
15 <tr>
15 <td align="right" style="font-family:arial;font-size:11pt;">
17 Credit Card Number:
18 </td>
19
20 <td align="left">
21 <h:inputText
22 value="#{myBean.creditCardNumber}"
23 maxlength="20" size="20"
24 id="idCreditCardNumber">
25 <example:regexValidator regex="([A-Za-z0-9 ]{0,20})"
26 errorMessage="The credit card number is invalid." />
27 </h:inputText>
28 </td>
29
30 </tr>
31 </table>
32 ...
33
34 </h:form>
35
36 </body>
37 </html>

Next, we'll walk through the setup needed to make this work.

Step 1. Create a file called regexValidatorTag.xml and place it in the WEB-INF directory.

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib xmlns="http://java.sun.com/JSF/Facelet">
  <namespace>http://example.regex</namespace>
  <tag>
    <tag-name>regexValidator</tag-name>
    <validator>
      <validator-id>exampleRegexValidator</validator-id>
    </validator>
  </tag>
</facelet-taglib>

Step 2. Add an entry to the faces-config that looks like this:

  <validator>
    <validator-id>exampleRegexValidator</validator-id>
    <validator-class>com.company.example.validator.RegexValidatorExample</validator-class>
  </validator>

Step 3. Add the namespace, xmlns:example=http://example.regex, to your jsf file as seen here:

  <html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:example="http://example.regex">

Step 4. Add a tag to the web.xml as follows:

  <context-param>
    <param-name>facelets.LIBRARIES</param-name>
    <param-value>/WEB-INF/regexValidatorTag.xml</param-value>
  </context-param>

Step 5. Create the custom validator class.

01	package com.company.example.validator;
02
03 import java.util.regex.Pattern;
04 import java.util.regex.Matcher;
05 import org.apache.commons.lang.StringUtils;
06 import javax.faces.validator.Validator;
07 import javax.faces.validator.ValidatorException;
08 import javax.faces.application.FacesMessage;
09 import javax.faces.component.StateHolder;
10 import javax.faces.component.UIComponent;
11 import javax.faces.context.FacesContext;
12
13 public class RegexValidatorExample implements Validator, StateHolder {
14
15 //required by StateHolder interface
16 private boolean isTransient;
17
18 //required by StateHolder interface
19 private boolean transientValue;
20 private String regex;
21 private String errorMessage;
22
23 public RegexValidatorExample() {
24 super();
25 }
26
27 public void validate(FacesContext context, UIComponent component, Object value)
28 throws ValidatorException {
29
30
31 //boundary checking
32 if ( null == regex || null == value) {
33 return;
34 }
35 String fieldValue= StringUtils.trimToEmpty((String)value);
36 Pattern p = Pattern.compile(getRegex());
37
38 if(StringUtils.isNotEmpty(fieldValue)){
39 Matcher matcher = p.matcher(fieldValue);
40 if(!matcher.matches()){
41 FacesMessage msg = new FacesMessage();
42 msg.setDetail(errorMessage);
43 msg.setSummary(errorMessage);
44 msg.setSeverity(FacesMessage.SEVERITY_ERROR);
45 throw new ValidatorException(msg);
46 }
47 }
48 }
49 public void restoreState(FacesContext context, Object state) {
50 Object values[] = (Object[]) state;
51 regex = (String) values[0];
52 errorMessage = (String) values[1];
53 }
54
55 public Object saveState(FacesContext arg0) {
56     Object values[] = new Object[2];
57     values[0] = regex;
58     values[1] = errorMessage;
59     return (values);
60 }
61 public boolean isTransient() {
62 return this.transientValue;
63 }
64 public void setTransient(boolean transientValue) {
65 this.transientValue = transientValue;
66 }
67 public String getErrorMessage() {
68 return errorMessage;
69 }
70 public void setErrorMessage(String errorMessage) {
71 this.errorMessage = errorMessage;
72 }
73 public String getRegex() {
74 return regex;
75 }
76 public void setRegex(String regex) {
77 this.regex = regex;
78 }
79 }

Line 16 declares the isTransient field and is required when using the StateHolder interface. The StateHolder, as its name implies, assists with saving the state between requests. Its corresponding getter/setters are on lines 61-66. Line 19 shows the transientValue field which is also required by the StateHolder interface. Line 20, regex, and line 21, errorMessage, have their corresponding getters/setters on lines 67-78. They are hydrated via Facelets which takes care of wiring the values of the tag attributes directly into the getters. Line 27 is where the validation begins. Its argument, Object value, corresponds to the value entered by the user in the form field. Line 36 uses the regex compile to create a Pattern. Lines 39 and 40 check to see that the field value passed in matches the regex pattern. If the field value does not match the regex expression, lines 41-44 set up the FacesMessage using the value in errorMessage. Lines 49-53, restoreState, and subsequently, lines 55-60, saveState, are necessary as they save and restore the attributes (i.e. regex, and errorMessage) being passed in across multiple requests. Line 56 sets up an array size of 2 because we have exactly 2 attributes in the tag. If we decided to use more attributes in the tag, the array size would also have to be augmented so that its size matches the number of tag attributes. The same holds true for lines 50-52.

Getting Form Fields Under Control With ui:include

Have you ever had a situation where, aside from the text label and the underlying bean, the same form field appears sprinkled in multiple locations on a form? Moreover, each occurrence of the same form field is laden down with complex validation and client side behavior. This is where Facelets template reuse comes in handy.

To illustrate, Figure 5 shows 2 sets of phone field groupings that will each re-use the same template. Other than their text label and underlying bean, they're identical from a functional perspective. For example, the Home Phone has a text label followed by an area code, a 3 digit phone prefix, and finally a 4 digit phone suffix. Under the covers it will support auto-tabbing and each its phone fields will have their own validator and display their own error message. The same can be said of the Cell Phone.



Figure 5. Two groupings of phone fields.

Before we go any further, let's take a quick look at the bean that will be used by our JSF page called MyBean. MyBean declares 2 Phone classes, homePhone and cellphone as seen below:

  class MyBean{
Phone homePhone;
Phone cellPhone;
  ...

In turn, the Phone class looks like this:

  class Phone{
String areaCode;
String prefix;
String suffix;
  ...

In Listing 6, lines 15-16 will be responsible for displaying the label text.
Lines 17-44 set up the 3 input fields.
The code uses our custom validator from the previous section, only this time the custom validator is being used to validate the individual phone fields.
Specifically, lines 22-23 for the area code, lines 31-32 for the prefix, and lines 42-43 for the suffix.
Lines 21, 30, and 41 refer to a JavaScript function called handleAutoTab which has been omitted since it's beyond the scope of this article. On lines 19, 27, and 37 the value attribute references something called a phoneRef. This is a reference to the MyBean's Phone object. Line 19 references the Phone object's areaCode. Line 27 references the Phone object's prefix, and so on. In the next listing we see the exact details of how this is set up.

Listing 6.  /WEB-INF/template/phone.xhtml
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
02                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03
04
05 <html xmlns="http://www.w3.org/1999/xhtml"
06 xmlns:ui="http://java.sun.com/jsf/facelets"
07 xmlns:f="http://java.sun.com/jsf/core"
08 xmlns:h="http://java.sun.com/jsf/html"
09 xmlns:c="http://java.sun.com/jstl/core"
10 xmlns:rich="http://richfaces.org/rich"
11 xmlns:example="http://example.regex">
12
13 <table>
14 <tr>
15 <td width="130" align="right"><h:outputText
16   value="#{label}" style="font-family:arial;font-size:11pt"/>:</td>
17 <td width="62">(<h:inputText
18 id="#{id}areaCode"
19 value="#{phoneRef.areaCode}"
20 immediate="true" maxlength="3" size="3"
21 onkeyup="handleAutoTab('#{id}areaCode')">
22 <example:regexValidator regex="([0-9]{3,3})"
23   errorMessage="Please enter a valid 3 digit area code." />
24 </h:inputText> )</td>
25 <td width="40"><h:inputText
26 id="#{id}prefix"
27 value="#{phoneRef.prefix}"
28 maxlength="3"
29 size="3"
30 onkeyup="handleAutoTab('#{myId}prefix')">
31 <example:regexValidator regex="([0-9]{3,3})"
32   errorMessage="Please enter a valid 3 digit phone prefix." />
33 </h:inputText></td>
34 <td align="center">-</td>
35 <td width="50"><h:inputText
36 id="#{id}suffix"
37 value="#{phoneRef.suffix}"
38 immediate="true"
39 maxlength="4"
40 size="4"
41 onkeyup="handleAutoTab('#{id}suffix')">
42 <example:regexValidator regex="([0-9]{4,4})"
43   errorMessage="Please enter a valid 4 digit phone suffix." />
44 </h:inputText></td>
45 </tr>
46 </table>
47 </html>

Listing 7 shows the code setup to utilize the phone.xhtml template. Lines 12-17 use the ui:include tag. Conceptually, the ui:include tag says that the lines between its start and end tag are going to be replaced with phone.xhtml. Lines 13-16 show the 3 parameters being passed. Line 15 assigns myBean.homePhone to the phoneRef attribute. Then within the phone.xhtml in Listing 6, lines 19, 27, and 37, use the phoneRef and bind the input field values to the corresponding fields contained within Phone homePhone. Lines 19-24 do the same thing only this time bind to the fields in Phone cellPhone.

Listing 7.  /WebContent/example/example4.xhtml
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
02                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03
04
05 <html xmlns="http://www.w3.org/1999/xhtml"
06 xmlns:ui="http://java.sun.com/jsf/facelets"
07 xmlns:f="http://java.sun.com/jsf/core"
08 xmlns:h="http://java.sun.com/jsf/html">
09 <body>
10 <h:form>
11 <f:view>
12 <ui:include src="/WEB-INF/template/phone.xhtml">
13 <ui:param name="label" value="Home Phone" />
14 <ui:param name="phoneRef"
15 value="#{myBean.homePhone}" />
16 <ui:param name="id" value="homePhone" />
17 </ui:include>
18
19 <ui:include src="/WEB-INF/template/phone.xhtml">
20 <ui:param name="label" value="Cell Phone" />
21 <ui:param name="phoneRef"
22 value="#{myBean.cellPhone}" />
23 <ui:param name="id" value="cellPhone" />
24 </ui:include>
25 </f:view>
26
27 ...
28 </h:form>
29 </body>
30 </html>

Putting it all Together

In this example we will show how to combine all the concepts we learned so far for maximum impact. The rendered form will look like Figure 6.



Figure 6. Putting it all together.

Listing 8 shows the code used to create the form. The code pulls together the concepts discussed in the previous sections. The form uses the decorator in 3 places. The decorator decorates each form section using the approach we saw earlier. In addition the modal panel decorator is nested within a decorator which further underscores the power and flexibility of Facelets.

Listing 8
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:example="http://example.regex">
<body>
<h:form>
<f:view>
<ui:decorate template="/WEB-INF/widget/formDecorator.xhtml ">

<table>
<td align="right" style="font-family:arial;font-size:11pt;" width="140">
Full Name:
</td>
<td align="left">
<h:inputText
value="#{myBean.fullName}"
maxlength="30" size="20"
id="idFullName">
<example:regexValidator regex="([A-Za-z ]{0,30})"
errorMessage="The full name is invalid." />
</h:inputText>
</td>
<td>
 
</td>
<tr>
<td align="right" style="font-family:arial;font-size:11pt;" width="140">
Credit Card Number:
</td>
<td align="left">
<h:inputText
value="#{myBean.creditCardNumber}"
maxlength="20" size="20"
id="idCreditCardNumber">
<example:regexValidator regex="([A-Za-z0-9 ]{0,20})"
errorMessage="The credit card number is invalid." />
</h:inputText>
</td>
<td>
 
</td>

</tr>
<tr>
<td align="right" style="font-family:arial;font-size:11pt;" width="140">
Secure Id:
</td>
<td align="left">
<h:inputText
value="#{myBean.secureId}"
maxlength="4" size="4"
id="idSecureId">
<example:regexValidator regex="([0-9 ]{0,4})"
errorMessage="The secure id is invalid." />
</h:inputText>
</td>

<td align="left">
  <ui:decorate template="/WEB-INF/widget/modalPanel.xhtml">
    <ui:param name="linkText" value="How do I find my credit card's secure id?"/>
    <ui:param name="title" value="Credit Card Security Code "/>
    <ui:param name="id" value="creditCard"/>
    The security code is the four digit number shown above
the credit card number on the right-hand.
  </ui:decorate>
</td>
</tr>
</table>
</ui:decorate>

<ui:decorate template="/WEB-INF/widget/formDecorator.xhtml ">

<table>
<tr>
<td colspan="3">
<ui:include src="/WEB-INF/template/phone.xhtml">
<ui:param name="label" value="Home Phone" />
<ui:param name="phoneRef" value="#{myBean.homePhone}" />
<ui:param name="id" value="homePhone" />
</ui:include>
</td>
</tr>
<tr>
<td colspan="3">
<ui:include src="/WEB-INF/template/phone.xhtml">
<ui:param name="label" value="Cell Phone" />
<ui:param name="phoneRef" value="#{myBean.cellPhone}" />
<ui:param name="id" value="cellPhone" />
</ui:include>
</td>
</tr>
</table>
</ui:decorate>
</f:view>

...
</h:form>
</body>
</html>

Facelets is replete with features that speed up development. To discover other interesting features please visit
http://facelets.java.net/nonav/docs/dev/docbook.html.

Nadine McKenzie has been a consultant in the software industry for more than 14 years. She is also a writer and an educator.
AttachmentSize
example1.png8.96 KB
example1b.png26.79 KB
example2.png12.88 KB
example2b.png47.02 KB
example4.png18.3 KB
example5.png68.75 KB
Related Topics >> Programming   |   Web Applications   |   Web Development Tools   |   Web Services and XML   |   Featured Article   |   

Comments

Hi Nadine, Great article! I already new it, but it's always ...

Hi Nadine,

Great article! I already new it, but it's always good to see things confirmed: Facelets rocks! There's one minor issue I have with the article though. Why are you still using HTML tables to position the elements? That's really oldfashioned, and I think we should not learn people to use tables for positioning anymore... But apart from that: just a great article, thanks!

Best regards,

Bart Kummel