4.4. Creating a Renderer

Component functionality typically centers around two actions:
decoding and encoding data.
Decoding is the process of converting incoming request parameters to the values of the component.
Encoding is the process of converting the current values of the component into the corresponding markup. In the
following figure you can see decoding and encoding occur in the JSF lifecycle:

Figure 4.3. Decoding and encoding in the JSF lifecycle

Thus, JSF components consist of two parts: the component class and the renderer.
The component class is responsible for the state and behavior of a UI component and will be discussed later in the "Configuring component" section.

The 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).

It is necessary to create following renderer classes for the <inputDate> component:

InputDateRenderer class where you should override encode() methods for encoding the markup and resources

InputDateRendererBase class where you should override decode() method.
You could also define associated converter in this class.

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 InputDateRenderer class.
The smartest way to create the InputDateRenderer class is a Templating mechanism,
one of the most convenient features of the Component Development Kit (CDK).

4.4.1. Templating

The Component Development Kit (CDK) allows to use 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 with the help of scriptlets.
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 for HTML 4.0 markup. 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:

<img> element with
"src",
"class",
"style" attributes which defines a default icon of the component.
In order to add an image to the Template you should register it with the help of
<f:resource> template tag
and bind to a variable specified by the "var" attribute:

Note:

As it is seen in the Template Skeleton the Renderer Baseclass is org.ajax4jsf.renderkit.AjaxComponentRendererBase.
You need to define Renderer Base class special for the <inputDate> component.
In the next section "Creating a Renderer Base class"
we will create Renderer Base class org.mycompany.renderkit.InputDateRendererBase.

4.4.2. Creating a Renderer Base class

After the component tree is restored on the Restore View Phase ,
each component in the tree extracts its new value from the request parameters
by using its decode() method. Then the value is stored locally on the component.

In order to create InputDateRendererBase class you should proceed to the
src/main/java/org/mycompany/renderkit
directory and create this class there:

The InputDateRendererBase class extends a HeaderResourcesRendererBase
class. In the HeaderResourcesRendererBase class all the encode() methods for
the right resources encoding
are already implemented, so in the InputDateRendererBase class you need to override
the decode() method only:

As you see in the example above the decode() method reads values from request parameters,
grabs the clientId from the component to identify the request parameter to be looked up.
The clientId is calculated as the fully qualified name of the component given its container path:
nameOfForm:nameOfComponent (for example myForm:inputDate).
The last step of the decode() method is to store the submitted value locally on the component.

Note:

By default, the base Renderer implementation returns the submittedValue directly without any conversion!
If you want to convert submitted value to a strongly typed object you should implement Converter
and the getConvertedValue() method in your Renderer class (in our case in the InputDateRendererBase class).

4.4.2.1. Creating a Converter

As it was mentioned before the <inputDate>
component at the Apply Request Values phase takes a value and pushes it
to the model as a strongly typed Date object.
Therefore you need to implement a Converter in the Renderer Base class and also check
whether a Converter has been already attached by the application developer.
If the conversion of the value fails, an error message associated with the component is generated
and queued on FacesContext.

The getConverter() method of the InputDateRendererBase class returns the a converter, as shown in the following example:

During the converter creation you should check whether the application developer has attached a Converter to the
<inputDate> component already
(for example, <f:convertDateTime>) .
If not you should follow the next steps:

create a new DateTimeConverter

get the locale for the client from the context with the help of the getLocale() method
and set it on the new Converter by means of the setLocale() method

set the time zone, date type, date style, and date pattern on the new converter with the help of
setTimeZone(), setType(), setDateStyle(), and
setPattern() methods respectively

return the Converter

After the Apply Request Values phase the application enters the
Process Validation phase during which the validate() method
calls the getConvertedValue() method on every submitted value and passes
the newly submitted value from the decode process.

The getConvertedValue() method converts the submitted value to a strongly typed
object (in our case Date) using the getAsObject() method.
Then the new strongly typed object is validated and if there are no errors
Process Validation phase ends. Otherwise the getConvertedValue() method
throws a ConverterException.

Finally on the Renderer Response phase the value of the component is rendered back to the view.
The converter is responsible for transforming the object data back in to a string representation, so you need to
implement getValueAsString() method:

4.4.3. Skinnability

One of the significant features of the Component Development Kit (CDK) is a skins-based technology which helps you to create a modern rich user interface look-and-feel.
RichFaces has a number of predefined skins you could use with the <inputDate> component.
But if you want to create your own skin, please, read carefully
the "Skinnability" section of the
RichFaces Developer Guide. You could find all necessary information about
Built-in skinnability in RichFaces, XCSS file format, Plug-n-Skin feature, etc. there.

It's time to create XCSS file. You should go to the src/main/resources/org/mycompany/renderkit/html/css
and create inputDate.xcss file there with the following skeleton: