Search code examples
jsfjsf-2faceletsmarkupcomposite-component

Declare markup outside cc:implementation and let the cc:implementation include it


Well. I created a custom component to CRUD and the form page is a parameter. In this case I need two pages, one to define the component and another with the form.

Is there any way to do that?

As follow:

Implementation:

Component

<cc:interface>
    <cc:attribute name="formPage" type="java.lang.String" required="true"/>
    .....
</cc:interface>

<cc:implementation>
...
    <h:form id="form-crud">
        <ui:include src="#{cc.attrs.formPage}" />       
    </h:form>
...
</cc:implementation>

Page 1: crud.xhtml

<ui:define name="content-template" >
    <comp:crud 
        paginaForm="crud-form.xhtml" />
</ui:define>

Page 2: crud-form.xhtml

<html ...
    <p:panelGrid id="grid-crud" columns="2" >
        <h:outputLabel for="dsName" value="Name: " />
        <p:inputText id="dsName"  value="#{crudBean.dsName}"/>
    </p:panelGrid>  
</html>

New Implementation (sample)

To simplify, I would like to have component defnition and form in the same page, something like that. Is it possible? I know I could use a template, but the custom componet has more attributes.

New Component

<cc:implementation>
...
    <h:form id="form-crud">
        <XX:SOMETING name="#{cc.attrs.formContent}" />      
    </h:form>
...
</cc:implementation>

New Page 1: new-crud.xhtml

...
<ui:define name="content-template" >
    <comp:crud 
        form="new-form" />

    <XX:SOMETING id="new-form">

        <p:panelGrid id="grid-crud" columns="2" >
            <h:outputLabel for="dsName" value="Name: " />
            <p:inputText id="dsName"  value="#{crudBean.dsName}"/>
        </p:panelGrid>  

    </XX:SOMETING>

</ui:define>
...

Solution

  • You can make use of <f:facet> exactly like as those work with e.g. <h:dataTable>/<h:column> header/footer.

    First declare a <cc:facet> with the desired name:

    <cc:interface>
        <cc:facet name="form" />
    </cc:interface>
    

    Then declare a <cc:renderFacet> in the desired place where it should end up:

    <cc:implementation>
        ...
        <h:form>
            <cc:renderFacet name="form" />
        </h:form>
        ...
    </cc:implementation>
    

    Now you can use it as follows:

    <comp:crud>
        <f:facet name="form">
            ...
        </f:facet>
    </comp:crud>
    

    Please note that this construct is also possible with "plain vanilla" Facelets tagfiles via <ui:define>/<ui:insert> mechanisms.