Conditionally render element's attribute in a composite component

Balázs Németh picture Balázs Németh · Oct 15, 2012 · Viewed 10.3k times · Source

I have the following composite component:

<?xml version="1.0" encoding="UTF-8"?>
<ui:component xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface>
        <composite:attribute required="true" name="field" />
        <composite:attribute required="true" name="value" />
        <composite:attribute required="false" name="size"/>
    </composite:interface>

    <composite:implementation>
    ...
            <div class="wrapper">
                <h:inputText value="#{cc.attrs.value}"
                    id="#{field.id}" 
                    rendered="#{field.rendered}" 
                    size="#{cc.attrs.size}">
                </h:inputText>
                <h:messages for="#{field.id}" styleClass="errorMessage"/>
            </div>
    ...
    </composite:implementation>
</ui:component>

The problem is that when I'm using this component without setting its size attribute, it still gets rendered as size=0 in the html input element.

What I want is to render the nested h:inputText's attribute only if it has a valid value (eg. not empty). Alternatively, I'd like to expose all attributes of the nested element if they are not overridden explicitly.

How would it be possible?

Answer

BalusC picture BalusC · Oct 15, 2012

You can use JSTL <c:if> to build the view conditionally and <f:attribute> to specify an attribute separately:

<h:inputText ...>
    <c:if test="#{not empty cc.attrs.size}">
        <f:attribute name="size" value="#{cc.attrs.size}" />
    </c:if>
</h:inputText>

An alternative is to specify a default for the composite component attribute:

<cc:attribute name="size" required="false" default="10" />