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
:
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
You find the source code at my GitHub repository
(Java classes, JSF file).
- Pseudo classes are CSS classes bearing no layout hints↩