I have a question about the idea behind the fact, that only UIForm
got the attribute prependId
. Why is the attribute not specified in the NamingContainer
interface? You will now probably say that's because of backward compability but I would preferre breaking the compability and let users which implement that interface, also implement methods for the prependId thing.
The main problem from my perspective about the prependId in the UIForm
component is, that it will break findComponent()
I would expect that if I use prependId
, then the NamingContainer
behaviour would change, not only related to rendering but also when wanting to search for components in the component tree.
Here a simple example:
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
Now when i want to get the panelGroup component I would expect to pass the string "group"
to the method findComponent()
, but it won't find anything, I have to use "test:group"
instead.
The concrete problem with that is, when using ajax with prependId="false"
. The ajax tag expects in the attributes update and process, that the values care of naming containers. It's a bit strange that when I use prependId="false"
that I have to specify the full id or path, but okay.
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
<h:form id="test1" prependId="false">
<h:commandButton value="go">
<f:ajax render="test:group"/>
</h:commandButton>
</h:form>
Well this code will render without problems but it won't update the panelGroup because it cannot find it. The PartialViewContext
will contain only the id "group"
as element of the renderIds. I don't know if this is expected, probably it is but I don't know the code. Now we come to the point where the method findComponent()
can not find the component because the expression passed as parameter is "group"
where the method would expect "test:group"
to find the component.
One solution is to write your own findComponent()
which is the way I chose to deal with this problem. In this method i handle a component which is a NamingContainer
and has the property prependId set to false like a normal UIComponent
. I will have to do that for every UIComponent
which offers a prependId attribute and that is bad. Reflection will help to get around the static definition of types but it's still not a really clean solution.
The other way would be introducing the prependId attribute in the NamingContainer
interface and change the behaviour of findComponent()
to work like described above.
The last proposed solution would be changing the behaviour of the ajax tag to pass the whole id, but this would only solve the ajax issue and not the programmatic issues behind the findComponent()
implementation.
What do you think about that and why the hell is it implemented like that? I can't be the first having this problem, but I wasn't able to find related topics?!