0

Forgive me I am not even sure my question is correctly stated. I am trying to unravel relationship between p:tab and h:panelGroup. I have very shallow understanding of JSF. I have following code.

<p:tabView id="view">
    <p:tab id="A">
        ...
        <p:ajax event="change" update="C,D" listener="#{bean.captureValue}"/>
    </p:tab>
    <p:tab id="B" titleStyleClass="x">
        <h:panelGroup id="C">
            <h:panelGroup rendered="#{bean.checkValue eq 'Yes'}"/>
                <f:facet name="title"><table>...</table></f:facet>
                <div>....</div>
            </h:panelGroup>
        </h:panelGroup>
        <h:panelGroup id="D">
            <h:panelGroup rendered="#{bean.checkValue eq 'No'}"/>
                <f:facet name="title"><table>.....</table></f:facet>
                <div>....</div>
            </h:panelGroup>
        </h:panelGroup>
    </p:tab>
</p:tabView>

So within component id="A", a user selects a value from drop down menu, bean captures it and dynamically show or hide component id="C" or "D" based on the value.

First time try, I didn't have any h:panelGroup tags. I used rendered attribute directly from p:tab component however I realized that unless I refresh the entire page, the bean.checkValue wouldn't know latest value captured. By reading many articles in this forum, I realized I have to wrap it with h:panelGroup which in turn worked by showing either h:panelGroup "C" or "D" based on the value selected from p:tab tag with id="A".

However the contents of f:facet tag is not visible anymore. It has html table tag which contains h:outputText with static value and p:graphicImage. I am not sure why and hope someone can solve this mystery.

Update:

Thanks to Arthur. I was able to fix the issue with his help. I paste here code that performs expected output.

<p:tabView id="view">
    <p:tab id="A">
        ...
        <p:ajax event="change" update="view" listener="#{bean.captureValue}"/>
    </p:tab>
    <p:tab id="B" titleStyleClass="x">             
          <f:facet name="title">
              <ui:fragment rendered="#{bean.checkValue eq 'Yes'}"/>
                 <table>...</table>
              </ui:fragment>
          </f:facet>
          <ui:fragment rendered="#{bean.checkValue eq 'Yes'}"/>
              <div>...</div>
          </ui:fragment>


           <f:facet name="title">
              <ui:fragment rendered="#{bean.checkValue eq 'No'}"/>
                 <table>...</table>
              </ui:fragment>
          </f:facet>
          <ui:fragment rendered="#{bean.checkValue eq 'No'}"/>
              <div>...</div>
          </ui:fragment>            
    </p:tab>
</p:tabView>
DaeYoung
  • 1,161
  • 6
  • 27
  • 59

1 Answers1

1

Facets are representing a named section within a container component. Container for your facets are in both cases <h:panelGroup> and this component doesn't define any facet which you could use. As you don't provide in your sample code any name for the facet (which is mandatory) I only assume that maybe you would like to use a title facet for a tab, as <p:tab> component define facet named "title". Then it should look like

<p:tab id="B">
        <f:facet name="title" >
            <h:outputText value="Test1" rendered="#{bean.checkValue}"/>
            <h:outputText value="Test2" rendered="#{!bean.checkValue}"/>
        </f:facet>
</p:tab>

, so you implement rendering logic inside facet value (you decide which title would be displayed. This logic could be also moved to backing bean. Keep in mind that in primefaces sometimes components doesn't handle very well and you could try then use them as an attribute instead of facets as stands in this post

It is also possible that you misunderstand meaning of facets. The best way to explain them are the facets defined i component. Authors of this component wanted to provide for users possibility to define header and footer of datatable. Then you, as a jsf user can compose header for instance, from other different components. You could also check this post where facets are also explained.

One more thing to add is that using <h:panelGroup rendered="#{bean.checkValue}"/> for render logic is considred as bad pattern as it is going to produce a <span> element in your code. Instead you should use <ui:fragment rendered="#{bean.checkValue}"/> which is intended for rendering logic and it won't produce any additional html code

Community
  • 1
  • 1
Artur Skrzydło
  • 1,135
  • 18
  • 37
  • @Arthur: Forgive me my late reply. I'd appreciate your detailed reply. Your reply helped me to have better understanding. Yet, I still have not fixed the problem. One thing I know for sure is I should not wrap f:facet with h:panelGroup. Although doing that render target component at real time (ajaxify). I will play more today by using ui:fragment inside of f:facet instead of using h:panelGroup. – DaeYoung Dec 27 '16 at 15:56
  • @DaeYoung You should write in more details what is inside facet, why you've used facet in your sample and when content of a facet was visible and when not. Just some more code snippets :) – Artur Skrzydło Dec 27 '16 at 16:56
  • f:facet contains simple table tag having two rows. one row inserts a static text and another row inserts an img file. div tag contains static text also. I forgot to mention only f:facet tag's content does not show however div tag's contents shows just fine. – DaeYoung Dec 27 '16 at 17:08
  • I am hoping to display contents of f:facet tag displays inside of tab. The contents of div tag always displays. If I remove f:facet tag, the contents of it displays in the space of div tag along with div tag contents. When I wrap f:facet tag with h:panelGroup + ui:fragment OR h:panelGroup + h:panelGroup just like in the question, ajaxify works but only contents of f:facet disappears or hidden. – DaeYoung Dec 27 '16 at 17:18
  • so let's back to question - why you've used facet ? You shouldn't use facet in that situation (read once again purpose of facets in a link which I've attached to my answer). You should just remove facet tag, leave it's content (because it works as you've written above) and along with div you should wrap it with ui:fragment. For more clarification try to write what you've tried in you question, by updating it with code snippets – Artur Skrzydło Dec 27 '16 at 17:31
  • I inherited a xhtml page that contains multiple tabs. All the tabs use f:facet tag to create a section where contents of xyz to be wrapped or displayed inside of tab NOT next to it where div tag's contents displays. I am working on the last tab (e.g. tab number 5). The contents of tab # 5 dynamically change based on the drop down selection from tab # 4. If I remove f:facet tag from the tab # 5, static text and an img file shows in the div tag's area not on the tab's space. I've been re-arranging primefaces and jsf tags 4 different ways to make it work. – DaeYoung Dec 27 '16 at 17:52
  • `` tags doesnt create a section. It implements a section within a container component. Which version of a jsf / primefaces do you use ? For tag it is mandatory to specify a name of a facet, but you haven't specified any. If you specify wrong name of a facet it shouldn't be displayed no matter what combination is used. Did you manage to display with its content at least once ? When you want to wrap some section you should use for instance not . Div tags area is also on tab's space. Maybe it is just a matter of styling with css ? – Artur Skrzydło Dec 27 '16 at 19:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/131623/discussion-between-daeyoung-and-artur-skrzydlo). – DaeYoung Dec 27 '16 at 20:11