Tuesday 19 May 2009

JSF: IDs and clientIds in Facelets

Updated 2009/11/24

This post is obsolete; go read this one instead: JSF: working with component identifiers The approach described in this post may fail if the component identifiers are not unique within the view.


Facelets is an alternative view technology to traditional JavaServer Pages and was designed with JavaServer Faces (JSF) in mind.

I've written before about how IDs work in JSF and how you can use custom expression functions to work with them (see JSF: working with component IDs (id vs clientId)). You cannot use JSP taglibs in Facelets, so if you want to invoke custom functions in your views you need to define them in Facelets' own tag libraries. The definitions are similar to those used in TLD files:

  <function>
    <function-name>clientId</function-name>
    <function-class>demo.faces.ClientIdUtils
    </function-class>
    <function-signature>java.lang.String
      findClientId(java.lang.String)</function-signature>
  </function>

The functions are imported via the tag library namespace, much like in JSPs:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:id="http://illegalargumentexception.googlecode.com/clientId">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>clientIdTest</title>
</head>
<body>
<h:outputText id="t1" value="Hello, World!" />
<br />
#{id:clientId('t1')}
</body>
</html>

A sample implementation can be downloaded from here.

3 comments:

  1. I don't think that idea around ${id:clientId('t1')} works too well in facelets. I mean facelets, not just jsf pages.

    To see what I'm talking about consider a facelet composition tag, say named MyControl, which use its ids inside; and then a page using these composition tags. Technically, your function will have to deal with many controls having the same id, and the goal is to pick the correct one.

    Thanks.

    ReplyDelete
  2. Hi Vladimir, thanks for commenting! Your comment prompted me to look at this approach again. Checking the JSF spec, it turns out there can be problems with this mechanism even in JSPs. For example, if a JSP had two separate form controls, it would be valid if they each contained a component with id='t1' because a form is a NamingContainer. I am thinking about a better way to do this.

    ReplyDelete
  3. Hello McDowell!

    Just in case, we exposed our implementation of the feature:
    http://www.nesterovsky-bros.com/weblog/2009/09/09/JSFClientId.aspx

    ReplyDelete

All comments are moderated