Skip to main content

skip to main content

developerWorks  >  Web development | Java technology  >

Craft Ajax applications using JSF with CSS and JavaScript, Part 1: Enhance the appearance of your JSF pages

Explore CSS support in standard JSF components

developerWorks
Document options
PDF format - Fits a4 and Letter

PDF - Fits a4 and Letter
187KB (22 pages)

Get Adobe® Reader®

Document options requiring JavaScript are not displayed

Discuss

Sample code


Rate this page

Help us improve this content


Level: Advanced

Andrei Cioroianu, Senior Java Developer and Consultant, Devsphere

29 Jan 2008

Typical Web applications require the use of Cascading Style Sheets (CSS) and JavaScript, together with a server-side framework, such as JavaServer Faces (JSF). CSS lets you change the visual characteristics of Web components within Ajax and other applications so they can have a pleasant and distinctive look. In the first installment of this two-part series, find out how to use the CSS-related attributes of standard JSF components. In addition, learn how to create a custom JSF component that sets the default styles of nested components, making it very easy to ensure a consistent look for all pages of your Web application. You can also use this technique to programmatically set other component attributes, as you'll see in Part 2, which will show how to make JSF forms more dynamic using JavaScript.

Using the style attributes of JSF components

Almost every JSF HTML component has two optional attributes named style and styleClass, which are rendered as the style and class attributes in HTML output. Some components, such as <h:dataTable> and <h:panelGrid>, have additional style attributes for their facets. This section discusses the CSS-related attributes of the JSF HTML library.

Linking CSS files to your JSF pages

If a Web page has unique styles, you can define style rules within the <style> element of the page's header. You can also specify the style information for a single JSF component using the style attribute. In most cases, however, you will probably prefer including the style rules in separate CSS files so you can apply them on multiple pages. You can link an external style sheet to a Web page using the <link> tag as shown in Listing 1:


Listing 1. Using the <link> tag
                
<link rel="stylesheet" type="text/css"
      href="${pageContext.request.contextPath}/MyStyles.css">
<link rel="stylesheet" type="text/css"
      href="<%=request.getContextPath()%>/styles/MoreStyles.css">

Using MyFaces Tomahawk
If you prefer using JSF components instead of HTML tags, you could use the <t:stylesheet> component of MyFaces Tomahawk, which renders the <link> tag for you.

In Listing 1, the href attributes contain absolute URIs. You can also use relative links for the CSS files, but it is better to include the context path with ${pageContext.request.contextPath} or <%=request.getContextPath()%> if the URLs of the JSF pages contain the /faces/ prefix. In this case, any relative link to a CSS file, image, or some other resource would lead to an HTTP request that contains the /faces/ prefix, which means that non-JSF files would be served by the Faces servlet. This works, but it is not very efficient. You can safely use relative links in your JSF-based applications if you request the JSF pages using the .faces suffix, which eliminates the issue described above.

Defining and using style rules

CSS files contain style sheet rules that apply to the HTML elements that can be rendered by JSF components, or that can simply be included between the components of the JSF page. For example, if you want your links to be underlined only when the mouse is over them, you will use the following rules (see Listing 2):


Listing 2. Style rules for links
                
a { text-decoration: none; }
a:hover { text-decoration: underline; }

These rules will apply to any link, whether the <a> element is directly included in the JSF page, or it is generated by a JSF component such as <h:commandLink> (see Listing 3):


Listing 3. HTML and JSF links
                
<a href="LinkStyles.faces">HTML Link</a>
<h:commandLink value="JSF Link"/>

Listing 4 shows how you can specify inline styles for a JSF component.


Listing 4. JSF component with style attribute
                
<h:commandLink value="Red Link" style="color: red"/>

In most cases, however, you will define style classes (see Listing 5) in the CSS files so you can use the same style rules for multiple components.


Listing 5. Style class example
                
.GreenClass { color: green; }

The style class name will be provided through the styleClass attribute to the JSF components as shown in Listing 6.


Listing 6. JSF component with styleClass attribute
                
<h:commandLink value="Green Link" styleClass="GreenClass"/>

You can find the code from Listings 1-6 in the LinkStyles.jsp and LinkStyles.css files from the sample code link in this article (see Download).

JSF components with multiple style classes

As mentioned earlier, some JSF components have more than one style attribute. For example, <h:message> and <h:messages> have the following ten CSS-related attributes:

  • style
  • styleClass
  • errorClass
  • errorStyle
  • fatalClass
  • fatalStyle
  • infoClass
  • infoStyle
  • warnClass
  • warnStyle

Only two of them are selected for each message, depending on the severity of the message being rendered. The JSF tags of the UISelectOne and UISelectMany components accept the enabledClass and disabledClass attributes for the items of the rendered lists. The <h:dataTable> and <h:panelGrid> tags have class attributes for the main table, header, footer, rows, and columns. The following examples show how to use the CSS-related attributes of a data table that is shown in the next screenshot.


Figure 1. TableStyles example
Table styles example

First, you need a data model for the table component. The OrderBean class (shown in Listing 7) extends javax.faces.model.ArrayDataModel. A real application would retrieve the model's data from a database, but for simplicity, OrderBean is initialized from a static array.


Listing 7. The OrderBean example
                
package jsfcssjs;

import javax.faces.model.ArrayDataModel;

public class OrderBean extends ArrayDataModel {
    private static ItemBean items[] = new ItemBean[] {
        new ItemBean("Domain Name",        3,   7.99f),
        new ItemBean("SSL Certificate",    1, 119.00f),
        new ItemBean("Web Hosting",        1,  19.95f),
        new ItemBean("Email Box",         20,   0.15f),
        new ItemBean("E-Commerce Setup",   1,  25.00f),
        new ItemBean("Technical Support",  1,  50.00f)
    };

    public OrderBean() {
        super(items);
    }
    
    public float getTotalPrice() {
        float total = 0;
        for (int i = 0; i < items.length; i++)
            total += items[i].getItemPrice();
        return total;
    }
    
}

The ItemBean class (see Listing 8) has three read/write properties named description, quantity, and unitPrice, and a read-only property named itemPrice.


Listing 8. The ItemBean example
                
package jsfcssjs;

public class ItemBean implements java.io.Serializable {
    private String description;
    private int quantity;
    private float unitPrice;
    
    public ItemBean() {
    }
    
    public ItemBean(String description, int quantity, float unitPrice) {
        this.description = description;
        this.quantity = quantity;
        this.unitPrice = unitPrice;
    }
    
    ...

    public float getItemPrice() {
        return unitPrice * quantity;
    }
    
}

The TableStyles.css file (shown in Listing 9) contains the styles used for the data table.


Listing 9. The TableStyles.css example
                
body     { font-family: Arial; }
.tablebg { background-color: #D0D0A0; }
.header  { font-weight: bold; }
.footer  { font-weight: bold; }
.text    { text-align: left; }
.number  { text-align: right; }
.graybg  { background-color: #DDDDDD; }
.whitebg { background-color: #FFFFFF; }

The TableStyles.jsp example (see Listing 10) contains a JSF table component that uses the style classes defined in TableStyles.css. The value of the styleClass attribute is used for the <table> element. The headerClass and footerClass attributes specify the styles for the header and footer cells of the table. The columnClasses attribute contains a comma-separated list of classes that are used for the <td> elements of the data cells.

Another list of classes can be specified through the rowClasses attribute. These are used for the <tr> elements of the table. In the TableStyles.jsp example, there are only two row classes, but the table has six rows. The JSF renderer of the <h:dataTable> component will alternate the two style classes, using the graybg class for the first, third, and fifth rows, and the whitebg class for the second, fourth, and sixth rows. The var attribute defines a variable named row, which is used to access the current row's data during rendering. The entire data is retrieved from the orderBean model, which is bound to the table through the value attribute.


Listing 10. The TableStyles.jsp example
                
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view>
<html>
<head>
    <title>Order Table</title>
    <link rel="stylesheet" type="text/css"
        href="<%=request.getContextPath()%>/styles/TableStyles.css">
</head>
<body>
    <h1>Order Table</h1>
    <h:dataTable id="table" var="row" value="#{orderBean}"
            styleClass="tablebg" headerClass="header" footerClass="footer"
            columnClasses="text,number,number,number"
            rowClasses="graybg,whitebg" border="0" cellpadding="5">
        <h:column>
            <f:facet name="header">
                <h:outputText value="Description"/>
            </f:facet>
            <h:outputText value="#{row.description}"/>
            <f:facet name="footer">
                <h:outputText value="Total Price"/>
            </f:facet>
        </h:column>
        <h:column>
            <f:facet name="header">
                <h:outputText value="Quantity"/>
            </f:facet>
            <h:outputText value="#{row.quantity}"/>
        </h:column>
        <h:column>
            <f:facet name="header">
                <h:outputText value="Unit Price"/>
            </f:facet>
            <h:outputText value="#{row.unitPrice}">
                <f:convertNumber type="currency" currencyCode="USD"
                    minFractionDigits="2" maxFractionDigits="2"/>
            </h:outputText>
        </h:column>
        <h:column footerClass="footer number">
            <f:facet name="header">
                <h:outputText value="Item Price"/>
            </f:facet>
            <h:outputText value="#{row.itemPrice}">
                <f:convertNumber type="currency" currencyCode="USD"
                    minFractionDigits="2" maxFractionDigits="2"/>
            </h:outputText>
            <f:facet name="footer">
                <h:outputText value="#{orderBean.totalPrice}">
                    <f:convertNumber type="currency" currencyCode="USD"
                        minFractionDigits="2" maxFractionDigits="2"/>
                </h:outputText>
            </f:facet>
        </h:column>
    </h:dataTable>
</body>
</html>
</f:view>

Listing 11 shows the HTML produced by the TableStyles.jsp page.


Listing 11. HTML produced by TableStyles.jsp
                
<html>
<head>
    <title>Order Table</title>
    <link rel="stylesheet" type="text/css"
        href="/jsf12css/styles/TableStyles.css">
</head>
<body>
    <h1>Order Table</h1>

<table id="table" class="tablebg" border="0" cellpadding="5">
<thead>
<tr>
<th class="header" scope="col">Description</th>
<th class="header" scope="col">Quantity</th>
<th class="header" scope="col">Unit Price</th>
<th class="header" scope="col">Item Price</th>
</tr>
</thead>
<tfoot>
<tr>
<td class="footer">Total Price</td>
<td class="footer"></td>
<td class="footer"></td>
<td class="footer number">$240.92</td>
</tr>
</tfoot>
<tbody>
<tr class="graybg">
<td class="text">Domain Name</td>
<td class="number">3</td>
<td class="number">$7.99</td>
<td class="number">$23.97</td>
</tr>
<tr class="whitebg">
<td class="text">SSL Certificate</td>
<td class="number">1</td>
<td class="number">$119.00</td>
<td class="number">$119.00</td>
</tr>
<tr class="graybg">
...
</tr>
<tr class="whitebg">
...
</tr>
<tr class="graybg">
...
</tr>
<tr class="whitebg">
...
</tr>
</tbody>
</table>

</body>
</html>

The last <h:column> component of the JSF table from the TableStyles.jsp example uses the footerClass attribute to specify two classes for the footer cell that show the order's total. The footer and number classes will be used for the <td> element of the footer cell. The footerClass attribute of the <h:column> component is available only in JSF 1.2. If you use an earlier JSF version, you would have to wrap the <h:outputText> component that renders the total within a <div> element so you can add the alignment effect of the number class (see Listing 12). The source code archive contains code samples for both JSF 1.1 and JSF 1.2.


Listing 12. JSF 1.1 version of the TableStyles.jsp example
                
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view>
    ...
    <h:dataTable ...>
        ...
        <h:column>
            ...
            <f:facet name="footer">
                <h:panelGroup>
                    <f:verbatim><div class="number"></f:verbatim>
                    <h:outputText value="#{orderBean.totalPrice}">
                        <f:convertNumber type="currency" currencyCode="USD"
                            minFractionDigits="2" maxFractionDigits="2"/>
                    </h:outputText>
                    <f:verbatim></div></f:verbatim>
                </h:panelGroup>
            </f:facet>
        </h:column>
    </h:dataTable>
    ...
</f:view>

Setting default styles for the JSF components

When building large applications with many JSF pages, you might dislike the idea of manually setting the styleClass attribute for every component instance. The standard JSF HTML components do not have default styles, but as you'll see in this section, it is possible to traverse the JSF component trees and programmatically set default style classes. To implement this operation, you need to know how these trees are created and how the HTML is generated.

Understanding how the JSF component trees are built

All faces requests are intercepted by the Faces Servlet, which is configured in the web.xml descriptor of any JSF-based Web application. For each request, the Faces Servlet initializes a javax.faces.context.FacesContext object and calls the execute() and render() methods of a javax.faces.lifecycle.Lifecycle instance. The execute() method handles all phases of the JSF request processing life cycle, except the last one (named Render Response), which is executed by the render() method.

State-saving methods
Depending on the value of the javax.faces.STATE_SAVING_METHOD context parameter, which can be set in the web.xml file, component trees are saved on the server or on the client. The JSF implementation can use the session scope to maintain the component trees on the server side. This method is efficient, but the JSF framework can get confused if the user clicks the browser's Back button, returning to an already submitted form. It is better to store each component tree on the client side where a hidden form element keeps the serialized copy of the tree associated to the page instance. Saving the component tree on the client side increases traffic and requires additional CPU resources for serializing and deserializing the object trees, but this method is more reliable than the use of the session scope.

In the first phase (named Restore View), the JSF implementation gets the application's view handler, which is a javax.faces.application.ViewHandler instance, and calls the restoreView() method if the request is a post back (for example, the user clicked a Submit button). In this case, the component tree should have been constructed and saved during the processing of a previous Faces request (see the sidebar on state-saving methods).

If the current request is not a post back (for example, the user clicked a Faces link), the JSF implementation calls the renderResponse() method of the current FacesContext and the createView() method of the ViewHandler instance. The renderResponse() call instructs the JSF implementation to jump from the current phase, which is still Restore View, to the Render Response phase. The createView() method of the default view handler creates only a javax.faces.component.UIViewRoot component. The rest of the tree will be created during the Render Response phase, when the JSF implementation calls the renderView() method of the view handler.

Whether the component tree is restored or must be created, the JSF implementation forwards the HTTP request to an associated JSF page at some point during the execution of the renderView() method. For example, if you requested /MyApp/MyPage.faces or /MyApp/faces/MyPage.jsp, the URI of the executed JSF page is /MyApp/MyPage.jsp.

Any JSF page contains component tags, such as <f:view> and <h:form>, which are backed by JSP tag handlers. These are Java™ classes implementing the interfaces defined in the javax.servlet.jsp.tagext package. When the page is executed, the JSP container creates instances of the tag handlers and calls their methods. Any tag handler of a JSF 1.2 component extends javax.faces.webapp.UIComponentELTag. If you use the JSF 1.1 API, the tag handler class extends javax.faces.webapp.UIComponentTag or javax.faces.webapp.UIComponentBodyTag. No matter which JSF version you use, the JSF tag handlers create the component instances during the Render Response phase if the component tree hasn't been restored in the Restore View phase.

You might be tempted to implement javax.faces.event.PhaseListener for setting the default styles, but this won't work when the user requests a page by clicking a link or entering the URL in the Web browser. In this case, the JSF implementation cannot restore the component tree, which must be created in the Render Response phase. Before this last phase, the component tree does not exist, and after rendering the response, it is too late to update the component styles because the HTML output has already been generated. Therefore, the default styles must be set during the execution of the Render Response phase before rendering the components.

Traversing components trees right before the rendering

JSF components have an interesting read-only property named rendersChildren. If this property is false, only the encodeBegin() and encodeEnd() methods will be called to render the component. If getRendersChildren() returns true, the encodeChildren() is also invoked during the Render Response phase. These methods normally delegate the rendering to another class, which must implement the javax.faces.render.Renderer interface, but JSF components can also generate the HTML themselves, without using renderers.

When using JSF 1.1, the encoding methods are initially called by the tag handler methods. If a component renders its own children, however, all tag handlers of the nested components stop calling the encoding methods because rendering becomes the responsibility of the component whose getRendersChildren() method returned true. This rendering process implemented in JSF 1.1 was efficient because it minimized buffering, but it required application developers to include the HTML content within <f:verbatim> components. In JSF 1.2, you don't have to use <f:verbatim> anymore because rendering is performed only after the whole component tree is created.

Whether you use JSF 1.1 or 1.2, the nested components are fully initialized and ready to be rendered when encodeChildren() is called. Therefore, here is the place where you get the chance to set the default styles. Next, you'll see how to create a custom component that sets the styleClass attribute for all its nested components, traversing the JSF component tree recursively.

The technique presented here can be used to set any attributes or properties of the JSF components, not just the default styles. Therefore it is a good idea to create a generic base class that can be reused later. The SetupComponent class extends the UIComponentBase class of the JSF API and defines an abstract method named setup(), which is invoked for every nested component whose rendering is enabled. The setupTree() method (shown in Listing 13) performs the recursive traversal of the JSF component tree.


Listing 13. The setup() and setupTree() methods of the SetupComponent class
                
package jsfcssjs;

import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
...
public abstract class SetupComponent extends UIComponentBase {

    protected abstract void setup(FacesContext ctx, UIComponent comp);

    protected void setupTree(FacesContext ctx, UIComponent comp) {
        if (!comp.isRendered())
            return;
        setup(ctx, comp);
        for (UIComponent child : comp.getChildren())
            setupTree(ctx, child);
    }
    ...
}

The getRendersChildren() method (see Listing 14), which is inherited from UIComponentBase, is overridden to return true so the setup component can control the rendering of its children.


Listing 14. The getRendersChildren() method of the SetupComponent class
                
public abstract class SetupComponent extends UIComponentBase {
    ...
    public boolean getRendersChildren() {
        return true;
    }
    ...
}

Listing 15 shows the encodeChildren() method, which is overridden to call setupTree() before invoking encodeTree() for each child.


Listing 15. The encodeChildren() method of the SetupComponent class
                
public abstract class SetupComponent extends UIComponentBase {
    ...
    public void encodeChildren(FacesContext ctx)
            throws IOException {
        if (!isRendered())
            return;
        setupTree(ctx, this);
        for (UIComponent child : getChildren())
            encodeTree(ctx, child);
    }
    ...
}

The encodeTree() method (see Listing 16) invokes the encoding methods for the current component and is called recursively for the child components if getRendersChildren() returns false.


Listing 16. The encodeTree() method of the SetupComponent class
                
public abstract class SetupComponent extends UIComponentBase {
    ...
    protected void encodeTree(FacesContext ctx, UIComponent comp)
            throws IOException {
        if (!comp.isRendered())
            return;
        comp.encodeBegin(ctx);
        if (comp.getRendersChildren())
            comp.encodeChildren(ctx);
        else
            for (UIComponent child : comp.getChildren())
                encodeTree(ctx, child);
        comp.encodeEnd(ctx);
    }

}

Creating and configuring a custom component

Listing 17 shows the DefaultStylesComponent class, which extends SetupComponent and implements the setup() method to set the styleClass attribute, whose value is built from the component family name and the renderer name.


Listing 17. The DefaultStylesComponent class
                
package jsfcssjs;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import java.util.Map;

public class DefaultStylesComponent extends SetupComponent {

    protected void setup(FacesContext ctx, UIComponent comp) {
        Map<String, Object> attrMap = comp.getAttributes();
        if (attrMap.get("styleClass") != null)
            return;
        String familyName = getLastName(comp.getFamily());
        String rendererName = getLastName(comp.getRendererType());
        if (familyName == null || rendererName == null)
            return;
        String className = "Default" + familyName;
        if (!familyName.equals(rendererName))
            className += rendererName;
        attrMap.put("styleClass", className);
    }
    
    protected String getLastName(String fullName) {
        if (fullName == null)
            return null;
        int dotIndex = fullName.lastIndexOf('.');
        if (dotIndex != -1)
            return fullName.substring(dotIndex+1);
        else
            return fullName;
    }

    public String getFamily() {
        return "DefaultStyles";
    }

}

The DefaultStylesComponent is configured in faces-config.xml, as shown in Listing 18.


Listing 18. Configuring DefaultStylesComponent in faces-config.xml
                
<faces-config ...>
    ...
    <component>
        <component-type>DefaultStylesComponent</component-type>
        <component-class>jsfcssjs.DefaultStylesComponent</component-class>
        <component-extension>
            <component-family>DefaultStyles</component-family>
        </component-extension>
    </component>

</faces-config>

Implementing the custom tag

The DefaultStylesTag class (see Listing 19) extends the UIComponentELTag class defined by the JSF 1.2 API and implements the getComponentType() and getRendererType() methods to return DefaultStylesComponent and null, respectively. If you use JSF 1.1, the tag class must extend UIComponentTag instead of UIComponentELTag.


Listing 19. The DefaultStylesTag class
                
package jsfcssjs;

import javax.faces.webapp.UIComponentELTag;

public class DefaultStylesTag extends UIComponentELTag {

    public String getComponentType() {
        return "DefaultStylesComponent";
    }

    public String getRendererType() {
        return null;
    }

}

The css.tld file (shown in Listing 20) defines the defaultStyles name and attributes of the custom tag. The support for the id, binding, and rendered attributes is inherited from UIComponentELTag.


Listing 20. The css.tld file for JSF 1.2 and JSP 2.1
                
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee" ... version="2.1">
    <tlib-version>1.0</tlib-version>
    <short-name>css</short-name>
    <uri>/css.tld</uri>
    <tag>
        <name>defaultStyles</name>
        <tag-class>jsfcssjs.DefaultStylesTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>id</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>binding</name>
            <required>false</required>
            <deferred-value>
                <type>jsfcssjs.DefaultStylesComponent</type>
            </deferred-value>
        </attribute>
        <attribute>
            <name>rendered</name>
            <required>false</required>
            <deferred-value>
                <type>boolean</type>
            </deferred-value>
        </attribute>
    </tag>
</taglib>

If you use JSF 1.1, the TLD file should conform to the syntax defined by the JSP 1.2 specification (see Listing 21).


Listing 21. The css.tld file for JSF 1.1 and JSP 1.2
                
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
    PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
    "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
    <tlib-version>1.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>css</short-name>
    <uri>/css.tld</uri>
    <tag>
        <name>defaultStyles</name>
        <tag-class>jsfcssjs.DefaultStylesTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>id</name>
            <required>false</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>
        <attribute>
            <name>binding</name>
            <required>false</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>
        <attribute>
            <name>rendered</name>
            <required>false</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>
    </tag>
</taglib>

Using the custom component in a JSF page

The developerWorks Ajax resource center
Check out the Ajax resource center, your one-stop shop for free tools, code, and information on developing Ajax applications. The active Ajax community forum, hosted by Ajax expert Jack Herrington, will connect you with peers who might just have the answers you're looking for right now.

The JSF example presented in this section shows how you can enhance the appearance of the JSF components, using background colors and borders.


Figure 2. DefaultStyles example
default styles example

Listing 22 shows the DefaultStyles.css file, which defines a few style classes that are used in the DefaultStyles.jsp example.


Listing 22. The DefaultStyles.css example
                
.DefaultForm {}
.DefaultPanelGrid { background-color: #FFFFFF; }
.DefaultInputText { background-color: #FFDDDD;
    border-style: ridge; border-width: thin; }
.DefaultInputTextarea { background-color: #DDFFDD;
    border-style: groove; border-width: thick; }
.DefaultSelectOneMenu { background-color: #DDDDFF;
    border-style: inset; border-width: medium; }
.DefaultCommandButton { background-color: #DDDDDD;
    border-style: outset; border-width: medium; }
.SpecialInputText { background-color: #DDFFFF;
    border-style: double; border-width: thick; }
.EnabledOption { color: #FF0000; }
.DisabledOption { color: #0000FF; }

The DefaultStyles.jsp example (see Listing 23) uses the <css:defaultStyles> component to set default styles for the JSF components that don't have the styleClass attribute. One of the components uses the SpecialInputText style class. The EnabledOption and DisabledOption classes are used for the items of a drop-down list.


Listing 23. The DefaultStyles.jsp example
                
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="css" uri="/css.tld" %>

<f:view>
<html>
<head>
    <title>Default Styles</title>
    <link rel="stylesheet" type="text/css"
        href="<%=request.getContextPath()%>/styles/DefaultStyles.css">
</head>
<body>
    <h1>Default Styles</h1>
    <css:defaultStyles>
        <h:form id="form">
            <h:panelGrid columns="1" border="0" cellspacing="5">
                <h:inputText id="text" size="30" value="default text style"/>
                <h:inputText id="special" size="30" value="special text style"
                    styleClass="SpecialInputText"/>
                <h:selectOneMenu id="menu" enabledClass="EnabledOption"
                        disabledClass="DisabledOption">
                    <f:selectItem itemValue="First" itemLabel="First"/>
                    <f:selectItem itemValue="Second" itemLabel="Second"/>
                    <f:selectItem itemValue="Third" itemLabel="Third"
                        itemDisabled="true"/>
                </h:selectOneMenu>
                <h:inputTextarea id="area" rows="5" cols="30"
                    value="default text area style"/>
                <h:commandButton id="button" value="Submit"/>
            </h:panelGrid>
        </h:form>
    </css:defaultStyles>
</body>
</html>
</f:view>

Listing 24 shows the HTML produced by the DefaultStyles.jsp page. You will notice that all form elements have a class attribute. Those class names that start with Default are set by the <css:defaultStyles> component.

Share this...

digg Digg this story
del.icio.us Post to del.icio.us
Slashdot Slashdot it!


Listing 24. HTML produced by the DefaultStyles.jsp
                
<html>
<head>
    <title>Default Styles</title>
    <link rel="stylesheet" type="text/css"
        href="/jsf12css/styles/DefaultStyles.css">
</head>
<body>
    <h1>Default Styles</h1>
    
<form id="form" ... class="DefaultForm" ...>
<input type="hidden" name="form" value="form" />
<table class="DefaultPanelGrid" border="0" cellspacing="5">
<tbody>
<tr>
<td><input id="form:text" type="text" ... 
    class="DefaultInputText" .../></td>
</tr>
<tr>
<td><input id="form:special" type="text" ... 
    class="SpecialInputText" .../></td>
</tr>
<tr>
<td><select id="form:menu" ... class="DefaultSelectOneMenu" ...>
    <option value="First" class="EnabledOption">First</option>
    <option value="Second" class="EnabledOption">Second</option>
    <option value="Third" disabled="disabled" 
        class="DisabledOption">Third</option>
</select></td>
</tr>
<tr>
<td><textarea id="form:area" ... 
    class="DefaultInputTextarea" ...> ... </textarea></td>
</tr>
<tr>
<td><input id="form:button" type="submit" ... 
    class="DefaultCommandButton" /></td>
</tr>
</tbody>
</table>
<input type="hidden" ... id="javax.faces.ViewState" value="..." />
</form>

</body>
</html>

Conclusion

This article explained the CSS support provided by standard JSF components. The simple ones have only two optional attributes named style and styleClass. The more complex components, such as grids and data tables, have additional CSS-related attributes for their facets and elements. This first part of the series also explained how the JSF component trees are built and how you can traverse these trees right before the component rendering, so you can add features, such as default styles. Stay tuned for Part 2, where you'll find JavaScript-based techniques for making JSF forms more dynamic.




Back to top


Download

DescriptionNameSizeDownload method
Sample application for this articlejsfcssjs_part1_src.zip25KBHTTP
Information about download methods


Resources

Learn

Get products and technologies

Discuss


About the author

Andrei Cioroianu is the founder of Devsphere, a provider of Java EE development and Ajax/JSF consulting services. He's been using Java and Web technologies since 1997 and has 10 years of professional experience in solving complex technical problems and managing the full life cycle of commercial products, custom applications, and open source frameworks. You can reach Andrei through the contact form at devsphere.com.




Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 

Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others.