Jim Driscoll's Blog

Notes on Technology and the Web

Another JSF 2.0 Ajax Component: Editable Text

leave a comment »

I was sitting in at a talk on Ajax components the other day, and they mentioned the Flickr style editable text. For those who’ve never experienced the Ajax joy that is Flickr, it’s a web based photography site. When viewing your own pictures, text such as the titles of your photos appears just as plain text, just as it does for other people’s photos. The difference is that when you hover the mouse pointer over the text, the background turns yellow, and “Click to Edit” appears as a tooltip. When you click, the text turns into an input field of type text, with a submit and cancel button appearing to the right.

I thought – I wonder how hard that would be as a component in JSF 2.0? The answer: Not too bad, about 150 lines of code. Here it is. (Note: if you haven’t yet read my previous examples, you may want to do that first – I’m assuming that you know a little bit about how this all fits together.)

We’ll create a component with some Ajax wiring and a little css. It will have two panels, which we’ll switch back and forth between, and a couple buttons. First, here’s how it’ll appear in the using page:

<ez:editText id="editText1" value="#{stringholder.str}"/>

Simple enough – a simple tag that takes a valueexpression in EL.

(Update: Acting on a reader’s suggestion, I’ve put some images of the component in action at the bottom of the post.)

Now, we’ll look at the component.

<composite:interface name="editText"
                     displayName="Editable Text Component"
                     shortDescription="Editable Text Component">
    <composite:attribute name="value" required="true" type="String"/>

    <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
    <h:outputScript name="editText/editText.js" target="head" />
    <script type="text/javascript">
        init("#{cc.clientId}", "#{cc.attrs.value}");
    <h:outputStylesheet name="editText/styles.css"/>
    <h:panelGroup id="edit1">
        <h:outputLink id="editLink" title="Click to edit" styleClass="editLink"
                      onclick="return linkClick('#{cc.clientId}');"
    <h:panelGroup id="edit2" style="display:none;">
        <h:inputText id="editInput" value="#{cc.attrs.value}" styleClass="editInput"/>
        <h:commandButton value="Submit" id="submit"
                         onclick="return submitButton('#{cc.clientId}', event);"/>
        <h:commandButton value="Cancel" id="cancel"
                         onclick="return cancelButton('#{cc.clientId}');"/>

There’s a lot to look at here, but it’s acutally not anything we haven’t done before, we’ll go through it line by line, looking at the bolded parts, which are the most important bits.

In the composite:interface section, we’re defining a required attribute, called “value”, which we already saw in the using page. We use it later in the places where we reference it as #{cc.attrs.value}. This, at least, should be straightforward by now.

We use three external files – the JSF 2.0 Ajax library, our own JavaScript file, and a CSS file. The three lines with outputScript and outputStyleSheet take care of that for us.

We also need to record what our client ID is, as we saw with my final Spinner example. We use the JavaScript init method to record that (we’ll look at the JavaScript next, be patient).

As I mentioned above, we’re using two panels (edit1 and edit2) – and we’ll switch between them. Edit2 starts off hidden (display: none;), so at first, this just looks like text. Edit1, however, is a link – we’ll leverage the hover capabilities of links to generate our change in background color and to get the tooltip I mentioned at the start of the example.

For all the active components, we’re wiring an onlick for them, which calls out to releavant JavaScript – they’ll also return false, since that’s required for us to *not* actually submit the entire form, but just the contents of the value expression instead.

So, having gone through all this, we’ll look at the JavaScript – it’s longer than our previous examples, but it’s really not doing anything we haven’t covered before.

if (!window["edittextdemo"]) {
    var edittextdemo = {};
function init(componentID, initialValue) {
    edittextdemo[componentID] = initialValue;
function toggle(idOn, idOff) {
    try {
        var elementon = document.getElementById(idOn);
        var elementoff = document.getElementById(idOff);
        elementon.style.display = "inline";
        elementoff.style.display = "none";
    } catch (ex) {
function submitButton(componentID, event) {
    try {
        var edit1 = componentID + ':edit1';
        var edit2 = componentID + ':edit2';
        toggle(edit1, edit2);

        var link = componentID + ':editLink';
        var input = componentID + ':editInput';
        var subButton = componentID + ':submit';
        var exec = subButton + ' ' + input;
        var rend = input + ' ' + link;
        jsf.ajax.request(document.getElementById(subButton), event, {execute: exec, render: rend});
        edittextdemo[componentID] = document.getElementById(input).value;
    } catch (ex) {
    return false;
function cancelButton(componentID) {
    try {
        var edit1 = componentID + ':edit1';
        var edit2 = componentID + ':edit2';
        toggle(edit1, edit2);
        var input = componentID + ':editInput';
        document.getElementById(input).value = edittextdemo[componentID];
    } catch (ex) {
    return false;
function linkClick(componentID) {
    try {
        var edit1 = componentID + ':edit1';
        var edit2 = componentID + ':edit2';
        var editInput = componentID + ':editInput';
        toggle(edit2, edit1);
    } catch (ex) {
    return false;

57 lines of code: Let’s go through it by function.

We start with creating an object if it doesn’t already exist. Why do this? To allow multiple components in a page. We’re going to use that object to save the component ID, which will change with every use.

init just saves the component ID, and associates it with the value that was set as the initial value. We’re saving that value for the cancelButton function, below.

toggle flips back in forth between our two panels, so you only see one at a time.

Next, we have the three functions that are called when user action happens. linkClick toggles the panels, and sets the focus on the newly revealed input text field.

The submitButton function toggles the panels, showing the link again, and then submits an ajaxRequest, executing the submit button (which is actually a no-op), and the input field, and rendering the input field and the link, which saves the new value to the bean. We also save the new value into a string in JavaScript, for use in restoring in case we choose cancel.

The cancelButton function again toggles the panels, showing the link, and restores the input field’s value to the last saved value, effectively syncing it up with the value on the server, without doing a request.

So that’s the JavaScript. Hopefully, you’re with me so far. Now we’ll take a peek at the CSS markup that makes it look like editable text.

.editClass {
    font-size: medium;
    font-style: normal;
    font-family: Arial, sans-serif;
.editLink {
    font-size: medium;
    font-style: normal;
    font-family: Arial, sans-serif;
a.editLink:link {text-decoration: none}
a.editLink:visited {text-decoration: none}
a.editLink:active {text-decoration: none}
a.editLink:hover {text-decoration: none; background-color: #eeee00;}

Not much going on here: Mostly, we’re just changing the look of the link.

So, that’s editable text. Is this a finished component? No, not really – we would still need to add css markup to give a constant width to the component. We need to add some JavaScript to allow displaying a link with no characters (the current implementation gets into an uneditable state if you change the string length to zero). But all that’s not specific to JSF 2.0. There’s also the need to add a waiting indicator – the traditional spinning wheel in case there’s an update pause after you hit submit. And oh, does this ever need error handling. Unfortunately, error handling and event processing are still undefined in JSF 2.0 – so that’s going to have to be a subject for another post.

To see the full source for this example, you can look under the Mojarra sourcebase. You can run it using GlassFish v3 Prelude, by updating to the JSF 2.0 API using the Update Center (make sure you’re up to date with Build 5 – this is cutting edge stuff).

As always, leave your questions below, and I’ll answer if I’m able. Next up – we’ll wire buttons to method actions in a composite component, for both Ajax and non-ajax use cases.

Per Request, here’s some images which show this tag in action.

Inital state:

On mouseover:

On onclick:

Data Entry:


Hopefully, that makes it easier to visualize what’s happening. I’ll include pictures from now on, thanks for the suggestion.

Update: I’ve updated this example to be more clear, and to conform with the latest JSF 2.0 PR release.
Update 2: I’ve again updated this example to conform to the JSF 2.0 FCS Spec.

(This article originally published on my java.net blog on November 24, 2008.)


Written by jamesgdriscoll

February 9, 2010 at 8:06 PM

Posted in ajax, JSF

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: