jump to navigation

JSF Custom Components with Facelets and IceFaces June 3, 2008

Posted by Phill in General J2EE.
Tags: , , , ,
trackback

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">
  <ul>
    <li class="selected"><a href="#">commandLink</a></li>
    <li><a href="#">commandLink</a></li>
  </ul>
</div>

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();
listElement.getChildren().add(link);
getChildren().add(listElement);
}

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!

Advertisements

Comments

1. michelle - June 8, 2008

How did this work out, have you tried icefaces.

Its a lot easier to create custom components.

Also facelets, I did something like what you want. I just wish my employer would let me publish it.

2. michelle - June 8, 2008
3. Phill - June 10, 2008

Hmmm, I couldn’t find any decent documentation on creating custom components in IceFaces and looking at the built-in IceFaces components didn’t help much.

Thanks for the link to your tutorial page, I will have a read through when I have time! 🙂

4. Daniel - October 17, 2008

Phill,

Is it possible to share your source code ? Currently I am facing the same problem (create a rather simple css – menu with IceFaces).
I agree with you, the IceFaces’ documentation for creating a component is poor (only the source code !).

TIA

5. Phill - October 17, 2008

Hi Daniel

Well, I can’t do a full source code post at the moment, but what I did was create a couple of subclasses of javax.faces.component.UIComponentBase.

This is basically the <LI> component:

public class ListComponent extends UIComponentBase {
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();

writer.startElement("li", this);
}

public void encodeEnd(...) {
writer.endElement("li");
}
}

then, what I needed to do in my navigation component was something like:


HtmlCommandLink commandLink = (HtmlCommandLink) context.getApplication().createComponent(HtmlCommandLink.COMPONENT_TYPE);
commandLink.setValue(menuTitle);
commandLink.setAction(Util.createConstantMethodBinding(action));
commandLink.setId("_navbar_" + section);

ListComponent li = new ListComponent();
li.getChildren().add(commandLink);

getChildren().add(li);

So, as you can see, the CommandLink component is actually added as a child of the List component, for each link in the menu.

I hope that’s a bit clearer anyway!

Phill


Sorry comments are closed for this entry

%d bloggers like this: