3

I'm somewhat new to JSF and Primefaces and I would like to make a composite component that contains a Primefaces GridPanel:

<composite:interface>
    <composite:attribute name="bind" type="com.whatever.IBackingBean"/>
    <composite:facet name="headerCols"/>
    <composite:facet name="bodyCols"/>
</composite:interface>
<composite:implementation>
<h:form>
    <p:panelGrid>
        <p:row>
            <composite:renderFacet name="headerCols"/>
            <p:column>
                <h:outputText value="Col1" />
            </p:column>
            <p:column>
                <h:outputText value="Col2" />
            </p:column>
            <p:column>
                <h:outputText value="Col3" />
            </p:column>
        </p:row>

        <p:row>
            <composite:renderFacet name="bodyCols"/>
            <p:column>
                <h:outputText value="#{cc.attrs.bind.prop1}" />
            </p:column>
            <p:column>
                <h:outputText value="#{cc.attrs.bind.prop2}" />
            </p:column>
            <p:column>
                <h:outputText value="#{cc.attrs.bind.prop3}" />
            </p:column>
        </p:row>
    </p:panelGrid>
</h:form>
</composite:implementation>

And would like to have a usage something like:

<x:mycomposite bind="#{myBackingBean}">
    <f:facet name="headerCols">
        <p:column>
             <h:outputText value="My Extra Prop"/>
        </p:column>
    </f:facet>
    <f:facet name="bodyCols">
        <p:column>
             <h:outputText value="#{myBackingBean.extraProp}"/>
        </p:column>
    </f:facet>
</x:mycomposite>

But when I do this... the Facets don't get added. I think this possibly has something to do with the inability to use <composite:renderFacet> as a parameter to <p:panelGrid> which is also (presumably) a composite.

Because I need to add columns, and not rows, I need to add in multiple locations so <composite:insertChildren> doesn't work.

I could presumably just use an attribute, but how does one pass an element value as the attribute value? As something like this doesn't seem to be available:

<x:mycomposite bind="#{myBackingBean}">
    <f:attribute name="headerCols">
        <p:column>
             <h:outputText value="My Extra Prop"/>
        </p:column>
    </f:attribute>
    <f:attribute name="bodyCols">
        <p:column>
             <h:outputText value="#{myBackingBean.extraProp}"/>
        </p:column>
    </f:attribute>
</x:mycomposite>

This assuming I modified the composite to:

<composite:interface>
    <composite:attribute name="bind" type="com.whatever.IBackingBean"/>
    <composite:attribute name="headerCols"/>
    <composite:attribute name="bodyCols"/>
</composite:interface>
<composite:implementation>
<h:form>
    <p:panelGrid>
        <p:row>
            #{cc.attrs.headerCols}
            <p:column>
                <h:outputText value="Col1" />
            </p:column>
            <p:column>
                <h:outputText value="Col2" />
            </p:column>
            <p:column>
                <h:outputText value="Col3" />
            </p:column>
        </p:row>

        <p:row>
            #{cc.attrs.bodyCols}
            <p:column>
                <h:outputText value="#{cc.attrs.bind.prop1}" />
            </p:column>
            <p:column>
                <h:outputText value="#{cc.attrs.bind.prop2}" />
            </p:column>
            <p:column>
                <h:outputText value="#{cc.attrs.bind.prop3}" />
            </p:column>
        </p:row>
    </p:panelGrid>
</h:form>
</composite:implementation>

Can anyone provide any alternative or advise on how to make the usage pattern work?

Thanks!

Jim
  • 668
  • 8
  • 22

1 Answers1

0

I'll post my workaround, which isn't technically a solution - so I don't think it's fair to quite mark it as such.

The reason why this isn't really a solution, is because it doesn't actually use the Primefaces <p:panelGrid> (whose layout options I'm slowly beginning to detest on whole - but that's another topic) and instead just uses an HTML5 <table>. It achieves the overall goal that I wanted, but will require me to ensure I add all the correct Primefaces styles to the table widget manually so the look and feel remain consistent.

If anyone has an alternate solution, I'd love to see it.

<composite:interface>
    <composite:attribute name="bind" type="com.whatever.IBackingBean"/>
    <composite:facet name="headerCols"/>
    <composite:facet name="bodyCols"/>
</composite:interface>
<composite:implementation>
<h:form>
<table>
    <tr>
        <composite:renderFacet name="headerCols"/>
        <th>
            <h:outputText value="Col1" />
        </th>
        <th>
            <h:outputText value="Col2" />
        </th>
        <th>
            <h:outputText value="Col3" />
        </th>
    </tr>

    <tr>
        <composite:renderFacet name="bodyCols"/>
        <td>
            <h:outputText value="#{cc.attrs.bind.prop1}" />
        </td>
        <td>
            <h:outputText value="#{cc.attrs.bind.prop2}" />
        </td>
        <td>
            <h:outputText value="#{cc.attrs.bind.prop3}" />
        </td>
    </tr>
</table>
</h:form>
</composite:implementation>
Jim
  • 668
  • 8
  • 22