Search code examples
jsfdatatablecomposite-component

h:dataTable composite component, cc.attrs.var, IllegalArgumentException


I'm trying to create my own dataTable like the primefaces one. The problem is that cc.attrs.var when used throws a IllegalArgumentException. So I'm wondering how I can have the var attribute like Primefaces.

<cc:interface>
    <cc:attribute name="value"/>
    <cc:attribute name="var"/>
    <cc:attribute name="styleClass"/>
</cc:interface>

<cc:implementation>

    <div>Previous</div>
    <div>Next</div>

    <h:dataTable value="#{cc.attrs.value}" var="#{cc.attrs.var}" styleClass="#{cc.attrs.styleClass}">
        <ui:insert/>
    </h:dataTable>

</cc:implementation>

Solution

  • As per the UIData#setValueExpression() javadoc, it's not allowed to have an EL expression in var attribute.

    Throws: IllegalArgumentException - if name is one of id, parent, var, or rowIndex

    Your best bet is to create a backing component wherein you manually evaluate and set the var attribute of the UIData component bound to <h:dataTable> during the postAddToView event.

    <cc:interface componentType="yourTableComposite">
        <cc:attribute name="value" />
        <cc:attribute name="var" />
    </cc:interface>
    <cc:implementation>
        <f:event type="postAddToView" listener="#{cc.init}" />
    
        <h:dataTable binding="#{cc.table}" value="#{cc.attrs.value}">
            <cc:insertChildren />
        </h:dataTable>
    </cc:implementation>
    

    @FacesComponent("yourTableComposite")
    public class YourTableComposite extends UINamingContainer {
    
        private UIData table;
    
        public void init() {
            table.setVar((String) getAttributes().get("var"));
        }
    
        public UIData getTable() {
            return table;
        }
    
        public void setTable(UIData table) {
            this.table = table;
        }
    
    }
    

    Note that I fixed the <ui:insert> to be <cc:insertChildren>. The <ui:insert> can only be used in <ui:composition>/<ui:decorate>.

    See also: