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?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Balázs Németh
  • 6,222
  • 9
  • 45
  • 60
  • Please be careful with tagging, a composite component is not a custom component. See also http://stackoverflow.com/questions/5704620/what-is-the-difference-between-custom-components-and-composite-components – BalusC Oct 15 '12 at 14:18
  • Thanks for the correction. I'm aware of that but I was a bit careless, maybe I need a couple of minutes break :S – Balázs Németh Oct 15 '12 at 14:27

3 Answers3

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" />
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you! It works but it's strange for me that if I add directly `` or `` I get `javax.servlet.ServletException: argument type mismatch` and if I add `` I get `Open quote is expected for attribute "value"`. – Balázs Németh Oct 15 '12 at 14:35
  • It has to be an `Integer`, not `String`. – BalusC Oct 15 '12 at 14:39
  • Yes, but how to add an `Integer` in the `value` attribute? With quotes it is interpreted as `String`, without quotes the exception is different. – Balázs Németh Oct 15 '12 at 14:42
2

Additional to BalusC's post:

You must use

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

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

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']}

Community
  • 1
  • 1
Revoman
  • 222
  • 2
  • 6