; last updated - 4 minutes read

Referencing by IDs isn't enough

While I like JSF as a component framework, I always feel JSF becomes less attractive once IDs come into play. The most common playground for IDs are AJAX requests, but they're also used in watermarks, sliders and even simple labels and error messages.

The problem with IDs is they aren't really flexible. They frequently don't survive simple operations such as refactoring the JSF code and copying fields. That's one of the reasons why I began to develop my AngularFaces library. But you don't have to go as far as to change your framework. The PrimeFaces JSF library has been offering improved search expressions for some time now, and they are even going to improve them with the upcoming version 4.0.

Client side search expressions

The attributes that are evaluated on the client side benefit from the power of jQuery. Basically that's the attribute update and the much less frequently used attribute process. jQuery expressions have to be surrounded by @(...) and are described in great detail at the jQuery documentation page. A very simple but useful idea is not to use CSS pseudo-classes instead of IDs.[1]

Server side search expressions

jQuery doesn't help you at all when it comes to attributes like for. Never mind. PrimeFaces also has a small server-side search expressions framework for you. PrimeFaces 3 already offered @this, @form, @all and @parent. Version 4.0 adds @composite (to resolve a Composite Component parent), @widgetVar(...) (to find a components by the name of it's widget) and @child(...) (to find a child element by its index). Maybe even more important is the ability to combine these components, as described in the PrimeFaces Blog and the PrimeFaces showcase.

And yet, until yesterday (Sept 30, 2013) something was missing. Most frequently I need the adjacent JSF elements:

Luckily the Search Expressions framework has been designed in a modular way. It can be extended in a very simple way. Actually, PrimeFaces committer Thomas Andraschko added @next and @previous to PrimeFaces after reading this article, and he made the modular API public to everyone. Thank you, Thomas!

Nonetheless I'd like to continue to explain my original example until I'll find another convincing search expression. First you have to implement a SearchExpressionResolver:

public class NextExpressionResolver implements SearchExpressionResolver { @Override public UIComponent resolve(UIComponent source, UIComponent last, String expression) { final UIComponent parent = last.getParent(); boolean selectNextOne = false; List children = parent.getChildren(); for (UIComponent c : children) { if (selectNextOne) { return c; } if (c == source) { selectNextOne = true; } } return null; } } public class PreviousExpressionResolver implements SearchExpressionResolver { @Override public UIComponent resolve(UIComponent source, UIComponent last, String expression) { final UIComponent parent = last.getParent(); UIComponent previous = null; List children = parent.getChildren(); for (UIComponent c : children) { if (c == source) { return previous; } previous = c; } return null; } }

We're almost done! All we have to do is do register the search expression at the SearchExpressionFactory:

SearchExpressionResolverFactory.registerResolver("@next", new NextExpressionResolver());

registerResolver also allows for parameters, such as @child().

Note user defined search expressions have to be preceded by an "@".

Live demo

As I mentioned above, @next and @last are now part of the coming PrimeFaces 4.0 release. For the sake of demonstration I also added @first and @last to AngularFaces. To use the AngularFaces search expressions you have to register them at the SearchExpressionFactory once. This is done automatically if you use <a:body>.

Note that the AngularFaces search expressions don't work with standard Mojarra components. I suspect this also applies to the original PrimeFaces search expressions.

Update November 15, 2013: JSF Spec Issue

Today Thomas told me he submitted a JSF specification JIRA issue. So chances are his Search Expression Factory makes its way into a future JSF version.

The search expressions are now part of the JSF 2.3 standard. Thanks, Thomas, for being so pernacious!


There a live demo at the AngularFaces showcase.

You find the source code at my GitHub repository

(Java classes, JSF file).


  1. Pseudo classes are CSS classes bearing no layout hints↩

Comments