The answer is hidden in the bottom of chapter 3.1.6 of JSF 1.2 specification:
3.1.6 Client Identifiers
...
The value returned from this method must be the same throughout the lifetime of the component instance unless
setId()
is called, in which case it will be recalculated by the next call togetClientId()
.
In other words, the outcome of getClientId()
is by default cached by the JSF component as implemented in UIComponentBase#getClientId()
(see also the nullcheck at line 275 as it is in Mojarra 1.2_15) and this cache is resetted when the UIComponentBase#setId()
is called (see also line 358 as it is in Mojarra 1.2_15). As long as you don't reset the cached client ID, it will return the same value on every getClientId()
call.
So, while rendering the children in encodeChildren()
implementation of your component or the renderer which shall most probably look like this,
for (UIComponent child : getChildren()) {
child.encodeAll(context);
}
you should for every child be calling UIComponent#setId()
with the outcome of UIComponent#getId()
to reset the internally cached client ID before encoding the child:
for (UIComponent child : getChildren()) {
child.setId(child.getId());
child.encodeAll(context);
}
The UIData
class behind the <h:dataTable>
implementation does that by the way also (see line 1382 as it is in Mojarra 1.2_15). Note that this is not JSF 1.x specific, the same applies on JSF 2.x as well (and also on UIRepeat
class behind Facelets <ui:repeat>
).