Conditionally render element's attribute in a composite component
Asked Answered
H

3

8

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?

Hymanhymen answered 15/10, 2012 at 13:57 Comment(2)
Please be careful with tagging, a composite component is not a custom component. See also #5705120Halophyte
Thanks for the correction. I'm aware of that but I was a bit careless, maybe I need a couple of minutes break :STonsure
H
13

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" />
Halophyte answered 15/10, 2012 at 14:17 Comment(3)
Thank you! It works but it's strange for me that if I add directly <f:attribute name="size" value="20"/> or <f:attribute name="size" value='20'/> I get javax.servlet.ServletException: argument type mismatch and if I add <f:attribute name="size" value=20/> I get Open quote is expected for attribute "value".Tonsure
It has to be an Integer, not String.Halophyte
Yes, but how to add an Integer in the value attribute? With quotes it is interpreted as String, without quotes the exception is different.Tonsure
L
2

Additional to BalusC's post:

You must use

type="int" in the cc:attribute-tag :

cc:attribute name="maxlength" type="int"

Limnetic answered 1/3, 2013 at 15:25 Comment(0)
Y
0

I believe there is an alternate method for accessing attributes. I've used this with JSF 2 when accessing an attribute named with a java reserved keyword.

{cc.attrs['size']}

Yokefellow answered 8/11, 2013 at 16:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.