Does JSF 2.0 have a built-in method for finding the client ID of another component? There are about a thousand client ID-related questions on SO and there are a lot of hack
This worked for me. I would be interested to know if it is Ok to write response like this though.
client.html
<h:outputText value="#{UIHelper.clientId('look-up-address-panel-id')}" />
UIHelper.java
@ManagedBean(name = "UIHelper", eager = true)
@ApplicationScoped
public class UIHelper
{
public String clientId(final String id)
{
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
final UIComponent[] found = new UIComponent[1];
root.visitTree(new FullVisitContext(context), new VisitCallback()
{
@Override
public VisitResult visit(VisitContext context, UIComponent component)
{
if (component.getId().equals(id))
{
found[0] = component;
return VisitResult.COMPLETE;
}
return VisitResult.ACCEPT;
}
});
return found[0] == null ? "" : "#" + found[0].getClientId().replace(":", "\\\\:");
}
}
Since this was among the first results of my google search and I wondered why I got a
javax.el.PropertyNotFoundException (Property 'itemId' not found [...])
when trying the accepted solution, I would like to share my solution for JSF 1.2:
The UIComponent
's method getClientId
needs a FacesContext
parameter (see UIComponent documentation). So add a binding to the backing bean and also another method that returns the clientId:
xhtml:
<h:button id="sampleButton" binding="#{backingBean.sampleButton}" value="Sample" />
<h:outputText value="sampleButton's client ID : #{backingBean.sampleButtonClientId}" />
Bean:
private UIComponent sampleButton;
public UIComponent getSampleButton() {
return sampleButton;
}
public void setSampleButton(final UIComponent sampleButton) {
this.sampleButton = sampleButton;
}
public String getSampleButtonClientId() {
final FacesContext context = FacesContext.getCurrentInstance();
return sampleButton.getClientId(context);
}
Notice that the bean you are binding your component to should be request scoped or else you could end up with a java.lang.IllegalStateException (duplicate Id for a component)
(compare to this topic).
You need to assign the component a variable name in the view scope by binding
attribute.
<h:button id="sampleButton" binding="#{sampleButton}" value="Sample" />
<h:outputText value="sampleButton's client ID : #{sampleButton.clientId}" />