Archive October 2009

Toggle view

Control rendering of UI elements based on validation results

In this post I describe how I tackled a problem that I faced quite often in the past. I need control over rendering a part of the UI based on validation results. E.g. when there is a validation message available for a certain input component then render a tooltip (containing a validation message) for the component.

JSF components offer a boolean rendered attribute that allows controling the rendering process. For complex decisions that means that a method on a managed bean would calculate the resulting state.

Exactly that was the solution that I was starting with for the problem described above.

public Map<String, Boolean> getHasMessages() {
	HashMap<String, Boolean> flags = new HashMap<String, Boolean>(1);
	Iterator<String> messages = FacesContext.getCurrentInstance().getClientIdsWithMessages();
	while (messages.hasNext()) {
		flags.put(messages.next(), Boolean.TRUE);
	}
	return flags;
}
<h:inputText label="Amount" id="amount" >
	<p:tooltip for="amount" showEvent="focus" hideEvent="blur" rendered="#{mbean.hasMessages['amount']}">
		<h:message for="amount" />
	</p:tooltip>
</h:inputText>

So I had a simple solution working fairly quickly. But let’s face it: It’s a clumsy solution that is hard to reuse and breaks when the id of the ui container around the input is changed.

To improve that, I decided that this requires a component that would be simple to reuse. As I’m using Facelets for the view I updated my knowledge of their support for custom components.

public class IfMessagesTagHandler extends TagHandler {
	private static final Logger LOGGER = LoggerFactory.getLogger(IfMessagesTagHandler.class);
	private static final String FOR_ATTRIBUTE_NAME = "for";
	private final TagAttribute forAttribute;

	public IfMessagesTagHandler(TagConfig config) {
		super(config);
		forAttribute = getAttribute(FOR_ATTRIBUTE_NAME);
	}

	public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
			ELException {
		if (forAttribute != null) {
			UIComponent forComponent = getForComponent(ctx.getFacesContext(), forAttribute.getValue(ctx), parent);
			if (forComponent != null) {
				if (ctx.getFacesContext().getMessages(forComponent.getClientId(ctx.getFacesContext())).hasNext()) {
					this.nextHandler.apply(ctx, parent);
				}
			} else {
				LOGGER.warn("No component {} found.", forAttribute.getValue(ctx));
			}
		} else if (parent != null) {
			if (ctx.getFacesContext().getMessages(parent.getClientId(ctx.getFacesContext())).hasNext()) {
				this.nextHandler.apply(ctx, parent);
			}
		}
	}
}

The above implementation accepts the optional attribute for that refers to a component id for which it tests if messages are available. In case the for attribute was not passed the tag would assume that the component to test for messages is the enclosing parent tag.

To register the tag handler a facelets tag library descriptor in META-INF is required.

<?xml version="1.0"?>

<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

<facelet-taglib>
	<namespace>http://martinahrer.at/jsf/facelets/blueprint</namespace>
	<tag>
		<tag-name>ifMessages</tag-name>
		<handler-class>at...view.facelets.IfMessagesTagHandler</handler-class>
	</tag>
</facelet-taglib>

A client would use that tag as:

<h:inputText label="Amount" id="amount" value="#{expenseSlipFormController.entity.amount}" required="true">
	<b:ifMessages >
		<p:tooltip for="amount" showEvent="focus" hideEvent="blur" style="myStyle">
			<h:message for="amount" />
		</p:tooltip>
	</b:ifMessages>
</h:inputText>

Upgraded to WordPress 2.8.4

Upgraded to WordPress 2.8.4

Roundcube web mail

I have been following the roundcube webmail project since version 0.1. Back then it was quite cumbersome to install on a Linux host. With 0.3 installation has turned into a cakewalk so I decided to try it now.

I only needed to update my PHP4 to PHP5, unpacked the installation package to the web root for the virtual host I created for roundcube, created a new mysql database and started the installation procedure.

Though it is still only a 0.3 version it has quite some impressive set of features. Of course due to its Web 2.0 nature it is a little bit slower than squirrel mail that I used earlier!

green red blue grey