I want to develope a JSF composite component using PrimeFaces library.
Basically I want to update my composite component. I have read some SO questions about it (JSF updating a composite component or JSF Updating Composite Component (Primefaces)). But in this case I only want to update certain parts of the component.
Here is an example. My component should be a label/message/value-part of a <p:panelGrid />
to get rid of all the noise of the <p:column/>
-tags.
<composite:interface>
<composite:attribute name="label" required="true" />
<composite:attribute name="value" required="true" />
</composite:interface>
<composite:implementation>
<p:column>
<!-- label -->
<p:outputLabel value="#{cc.attrs.label}" for="id_inputtext"/>
</p:column>
<p:column>
<!-- message -->
<p:message for="id_inputtext" />
</p:column>
<p:column>
<!-- inputtext -->
<p:inputText id="id_inputtext" value="#{cc.attrs.value}"/>
</p:column>
</composite:implementation>
To use this composite component I can simply put it in a panelgrid like so.
<p:panelGrid>
<p:row>
<mycomponent:columnSet id="c1" label="label" value="hello world"/>
<mycomponent:columnSet id="c2" label="label2" value="hello world2"/>
</p:row>
<p:row>
<mycomponent:columnSet id="c3" label="label3" value="hello world3"/>
<mycomponent:columnSet id="c4" label="label4" value="#{bean.someValue}"/>
</p:row>
</p:panelGrid>
In this case I can not surround the content of the component with an HTML container element like <div/>
or <span/>
like it is described in the above links. That would result in weird HTML because it would be within the generated table.
What I want to do in the example above is to update the <p:outputLabel/>
, the <p:message/>
and the <p:inputText/>
from outside of the component. In a perfect world I want to update these three components independently from each other (but I guess that is even more complicated than updating all at once).
What I currently do to get this to work is kind of cheating. I create a <composite:attribute name="id" />
and give the three components fixed IDs based on a convention using the composite component id. That works but is pretty poor because using the composite component, one needs to know the inner implementation of the it.
Does anyone have an idea to solve this requirement in a nicer way?
<composite:interface>
<composite:attribute name="id" required="true" />
</composite:interface>
<composite:implementation>
<p:column>
<!-- label -->
<p:outputLabel id="#{cc.attrs.id}_label"/>
</p:column>
<p:column>
<!-- message -->
<p:message id="#{cc.attrs.id}_message" />
</p:column>
<p:column>
<!-- inputtext -->
<p:inputText id="#{cc.attrs.id}_value"/>
</p:column>
</composite:implementation>
EDIT
Thanks for the quick response in the comments.
As to the tag files: Indeed, I must admit that I avoided dealing with tag files because composite components are so much easier to handle, my bad.
Anyway, I just read some stuff, made a quick-and-dirty prototype, but came to the conclusion that (although it might be a good and proper way to use tag files in this label/message/input-situation) I have the same issue as with the composite component: To update the components inside the tag file I need to know the inner implementation of it (that is the same as described in my workaround).
I want to update the composite component/tag file from outside with a «single handle» and treat it as a black box.
If I could wish for a feature I want something to say «do the update» on the composite component/tag file. And within the composite component/tag file I can define which components should be updated if «do the update» is triggered. Something like three separate <div id="#{cc.clientId}"/>
surrounding every component I want to update (which obviously is not possible like that).
Because I guess that this is nearly impossible, I would also be happy with a way to update a composite component/tag file as a whole, meaning to update every component within the black box.