Don’t you know this: You have an application using some dialogs and each dialog contains some required fields and some, whiche are not mandatory. To disinguish these two kinds of fields, the required fields should be marked, e.g. with an asterisk. Now, what we want to do, is to write a central function which might be used in all pages. The idea is quite simple: Before rendereing, check all labels and theis associated input components. If the input is required, mark it.
The central place might be a faclets template.
<f:metadata> <f:phaseListener type="calculator.LifeCycleListener"/> </f:metadata>
This registers a phase listener with it’s full qualified name. Within this listener, we will check all components and modify the label.
package calculator; import javax.faces.component.UIComponent; import javax.faces.component.UIInput; import javax.faces.component.UIViewRoot; import javax.faces.component.html.HtmlOutputLabel; import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; /** * * @author mmueller */ public class LifeCycleListener implements PhaseListener { UIViewRoot _root; @Override public void beforePhase(PhaseEvent event) { _root = event.getFacesContext().getViewRoot(); if (_root != null && event.getPhaseId() == PhaseId.RENDER_RESPONSE) { markLabels4Required(_root); } } @Override public void afterPhase(PhaseEvent event) { } @Override public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } private void markLabels4Required(UIComponent parent) { String marker = " *"; for (UIComponent child : parent.getChildren()) { if (child instanceof HtmlOutputLabel) { HtmlOutputLabel label = (HtmlOutputLabel) child; String targetId = label.getNamingContainer().getClientId() + ":" + label.getFor(); UIComponent target = _root.findComponent(targetId); if (target instanceof UIInput) { UIInput input = (UIInput) target; String labelText = label.getValue().toString(); if (input.isRequired() && !labelText.endsWith(marker)) { label.setValue(labelText + marker); } if (!input.isRequired() && labelText.endsWith(marker)) { label.setValue(labelText.substring(0, labelText.length() - marker.length())); } } } markLabels4Required(child); } } }
The PhaseListener may follow all phases. Here, we only use before RenderResponse. In this special case there is an alternative available:
<f:metadata> <f:event type="preRenderView" listener="#{phaseBean.preRenderView}"/> </f:metadata>
PhaseBean:
[...] UIViewRoot _root; public void preRenderView(ComponentSystemEvent e) { _root = FacesContext.getCurrentInstance().getViewRoot(); markLabels4Required(_root); } [...]
This article is just to give you a quick information. Later on, I might include this in my JSF tutorial and add some more explanation.
Update: The code shows you an approach I used once ago. At the end of 2011 I switched to manipulate CSS. The principal approach is still the same, but instead of exchanging content (the “*”), I simply change style.
To web development content.
Do you want to support this blog? You may help to finance the needed hardware.
Want to read more about software development? Purchase one of my books:
Start application development with Java. Learn development foundation, quality control and more.
A Journey through Java EE Technologies whilst developing Web Applications with JavaServer Faces.
Java Lambdas and Parallel Streams
The compact starter: Foundation, supporting structures, parallel processing
No software development, just nature:
A photographic image book. Get it for free. Or pay whatever you like.
Nice post. I was checking constantly this blog and I’m
inspired! Extremely helpful information specifically
the remaining part 🙂 I take care of such info much.
I was looking for this particular info for a very long time.
Thanks and good luck.