JBoss.orgCommunity Documentation

Chapter 4. inputDate component development

We a going to create the <inputDate> component that can take a value, process that value, and then push it back to the underlying model as a strongly typed Date object.

The <inputDate> component allows to attach a converter in order to set the desired date format such as mm/dd/yyyy. So the component could convert and validate the date entered by user.

At first we need to create a project for the component itself. In the library directory Sandbox you just created, launch the following command (all in one line):


mvn archetype:create -DarchetypeGroupId=org.richfaces.cdk -DarchetypeArtifactId=maven-archetype-jsf-component -DarchetypeVersion=3.2.1.GA -DartifactId=inputDate
    

As is easy to see a new directory with the name inputDate will be created. It does not have any components in it yet, but it has this predefined structure:


Here are main directories with descriptions:


Now you should add maven-compiler-plugin to the plugins section in the inputDate/pom.xml file:


...
<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <inherited>true</inherited>
    <configuration>
        <source>1.5</source>
        <target>1.5</target>
    </configuration>
</plugin>
...
    

Finally your inputDate/pom.xml should look like this one:


<?xml version="1.0"?>
<project>
    <parent>
        <artifactId>sandbox</artifactId>
        <groupId>org.mycompany</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.mycompany</groupId>
    <artifactId>inputDate</artifactId>
    <name>inputDate</name>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.richfaces.cdk</groupId>
                <artifactId>maven-cdk-plugin</artifactId>
                <version>3.2.1.GA</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>    
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <library>
                        <prefix>org.mycompany</prefix>
                        <taglib>
                            <shortName>inputDate</shortName>
                        </taglib>
                    </library>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <inherited>true</inherited>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.richfaces.framework</groupId>
            <artifactId>richfaces-impl</artifactId>
            <version>3.2.1.GA</version>
        </dependency>
    </dependencies>
</project>

Let's create a skeleton for the <inputDate> component.

You need to go to the inputDate directory and then launch the following command:


mvn cdk:create -Dname=inputDate

As a result three artifacts will be created:

In order to build the component you should stay in the inputDate directory and launch the following command:


mvn install

This command generates and compiles the library and then creates a result JAR file. A directory named target will be created along with a src directory. If you get a file named target/inputDate-1.0-SNAPSHOT.jar, everything is set up successfully.

If you want to rebuild the component you could use the following command:


mvn clean install
    

It is a good idea to create at first a prototype of the intended markup. You will find out which markup elements the component has to generate and also which renderer-specific attributes are needed in order to parameterize the generated markup.

The <inputDate> component consists of an HTML form <input> element, an <img> element, and <div> element:


...
<div title="Date Field Component">
    <input name="dateField" value="01 January 2008" />
    <img class="overlay" src="inputDateOverlay.png" />
</div>
...   

As it is shown in the listing above there are three HTML attributes - "title" , "name" , and "value" - are needed to be parameterize the generated markup.

You map the HTML attributes to the corresponding UIComponent attributes:


...
<div title="[title]">
    <input name="[clientID]" value="[converted value]" />
    <img class="overlay" src="inputDateOverlay.png" />
</div>
...
    

All information about styles applied to the <inputDate> component is considered in the following chapter.

This is the result of your prototype which shows a simple page with an input field and an icon indicating that this is a date field:


Renderer is responsible for the JSF component representation. It generates the appropriate client-side markup, such as HTML, WML, XUL, etc. Renderer is also responsible for the converting information coming from the client to the proper type for the component (for example, a string value from the request is converted to a strongly type Date object).

You could actually implement the renderer-specific component subclass that exposes client-side attributes such as "style" , "class" , etc. It is common practice to implement the client-specific component subclass to make some aspects of application development easier, but in our case we do not need to do it. The <inputDate> is a simple UIInput component, therefore InputDateRenderer class generates all the markup itself.

It is a time to start creating the Renderer.

One of the most convenient features of the Component Development Kit (CDK) is a Templating mechanism.

The Component Development Kit (CDK) allows to use the templates for generation Renderer class.

Templates are JSP-like markup pages with special tags that are converted into Renderer by a build script.

It's possible to use evaluated expressions in components templates. It's also possible to create the base class for a template to implement additional functions in it, so as the functions could be called from the template. Hence, in the generated Renderer class there are corresponding function calls on the place of these elements.

Let's create the template. At first you should proceed to the inputDate/src/main/templates/org/mycompany directory where htmlInputDate.jspx template file is stored. This file contains a Template Skeleton like this one:



<?xml version="1.0" encoding="UTF-8"?>
<f:root 
    xmlns:f="http://ajax4jsf.org/cdk/template" 
    xmlns:c=" http://java.sun.com/jsf/core" 
    xmlns:ui=" http://ajax4jsf.org/cdk/ui"
    xmlns:u=" http://ajax4jsf.org/cdk/u"
    xmlns:x=" http://ajax4jsf.org/cdk/x"
    class="org.mycompany.renderkit.html.InputDateRenderer"
    baseclass="org.ajax4jsf.renderkit.AjaxComponentRendererBase"
    component="org.mycompany.component.UIInputDate" 
    >
    <f:clientid var="clientId"/>
    <div id="#{clientId}"
        x:passThruWithExclusions="value,name,type,id"
        >
    </div>
</f:root>
    

According to the created UI prototype you need to extend Template Skeleton with proper elements. Here is a full example for the <inputDate> component:

htmlInputDate.jspx.

Registering component resources

UI Component generation

Creating a JSP tag handler and TLD