jump to navigation

JSF Custom Components with Facelets and IceFaces June 3, 2008

Posted by Phill in General J2EE.
Tags: , , , ,
comments closed

I was having fun earlier trying to get a custom component working. I wanted to create a dynamic menu component, which I didn’t think was easily possible with standard JSF components.

What I wanted rendered was something like this:

<div class="navbar">
    <li class="selected"><a href="#">commandLink</a></li>
    <li><a href="#">commandLink</a></li>

Fairly simple, wouldn’t you think?

Well, actually it’s not that difficult – once you know how!

The problem comes with the way child components are rendered. I was creating a new HtmlCommandLink in my custom component, and then using encodeBegin(context) and encodeEnd(context) to render them.

However, I found that when you clicked on the links, nothing would happen! I looked at the source code, and couldn’t actually see anything wrong. It all looked fine… my only thought was that somehow IceFaces wasn’t picking up the components if I rendered them directly.

One idea was to actually add the commandLinks to the list of children, i.e. getChildren().add(commandLink). However, this doesn’t render components in the way that you want – i.e., I wanted all of the links surrounded by <li> and </li>!

In the end, what I did was create another custom component (ListElementComponent), and have it render an “<li>” and “</li>” in the encodeBegin(…) and encodeEnd(…) methods respectively. Then, I added the commandLink as a child of the ListElementComponent, and added the ListElementComponent as a child of my custom component.

Clear? Probably not!

Basically, the logic was as following:

for (each menu item) {
link = createCommandLink();
listElement = new ListElementComponent();

This seemed to force JSF / IceFaces to render the HTML as I wanted it.

I don’t know if there was an easier way of doing it, but unfortunately the documentation on custom components in JSF isn’t exactly brilliant!