What I would like to achieve is to be able to address some JSF components from within other naming container.
Usecase: composite component which encapsulates some features using - for a field which is defined out of the composite component.
Some code:
<form id="foo">
...
<label for="nameTxt">Name:</label>
<component:customError forField="nameTxt" />
<h:inputText id="nameTxt" />
...
</form>
and the component:
<composite:implementation>
<h:panelGroup id="errorComponent">
...
<h:message for="#{cc.attrs.forField}" id="errorMsg" style="display:none;" />
...
</h:panelGroup>
</composite:implementation>
The problem is that on rendering the message I get:
Could not render Message. Unable to find component 'nameTxt' (calling findComponent on component 'j_id963445801_469fc056:errorMsg')
I think I understand that the problem lies in the fact the the field "nameTxt" and the message "errorMsg" lie in other naming-containers. So what I would have and like to do is to specify the path/id of "nameTxt" in relation to some common ancestor.
After studying shortly the algorithm UIComponentBase:findComponent I do not actually see any other way of adressing cross naming-containers than by specyfing whole (absolute) id-path from the root (i.e. ":foo:...:nameTxt"). And this is both clumsy and prone for errors after changing the page structure.
So - how to address properly the field "nameTxt" from within the message in the composite component?
I can reproduce your problem on MyFaces 2.1.3, but not on Mojarra 2.1.4 (and also not on older Mojarra 2.0.2). This is likely a bug in MyFaces, you'd need to report it to the MyFaces guys. In the meanwhile, I don't see any other option than (temporarily) replacing the JSF implementation by Mojarra. It has however its own share of issues as well, mainly with its broken <ui:repeat>
and partial state saving implementations.
Update: I found a workaround, it's however a bit clumsy:
<component:customError forField=":#{nameTxt.clientId}" />
<h:inputText id="nameTxt" binding="#{nameTxt}" />
This will lookup using the absolute client ID instead of relative client ID. You'd only need to remove style="display:none"
from your <h:message>
to solve a different matter.