views:

43

answers:

2

This must be simple. I am trying to pass sub-element into a JSF component. I have my component declared as:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:composite="http://java.sun.com/jsf/composite"&gt;

<composite:interface>
</composite:interface>

<composite:implementation>
    <div style="border: 1px solid black;">
        <ui:insert />
    </div>
</composite:implementation>

</html>

Then I use this in a page by:

<box:box>
    <p>Hello world!</p>
</box:box>

Unfortunately, the box renders ok (the black border) but the "Hello world!" text is not included within it. I also tried more verbose syntax by using <ui:insert name="content"> and calling by <ui:define name="content">Hello World!</ui:define> but it didn't work.

Where might I be making a mistake?

A: 

You have to send the content as parameter:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

    <html
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:composite="http://java.sun.com/jsf/composite"&gt;

    <composite:interface>
         <composite:attribute name="content"/>
    </composite:interface>

    <composite:implementation>
        <div style="border: 1px solid black;">
             <h:outputText value="#{cc.attrs.content}" escape="false"/>
        </div>
    </composite:implementation>

</html>

and in your code:

<box:box content="<p>Hello world!</p>" />

I added the escape="false" since you are using HTML tags inside the EL expression.

Read more about composite elements in David Geary’s article

Odelya
Yes this would be one way to do that but it's very ugly design. Also, what if I have a longer section of XHTML/JSF code that I want to use as sub-element? Passing the content as string attribute is unconvenient. Instead, the style I tried (using `<ui:insert />`) should work, as lined in http://www.packtpub.com/article/creating-composition-components-in-jsf-2.0 (look at the chapter "Passing sub-elements to composition components"). This same approach is also covered in book JSF 2 APIs and JBoss Seam. However, in my tests it fails.
Tuukka Mustonen
+3  A: 

Ok I figured it out. You should use <composite:insertChildren /> instead as in:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:composite="http://java.sun.com/jsf/composite"&gt;

<composite:interface>
</composite:interface>

<composite:implementation>
    <div style="border: 1px solid black;">
        <composite:insertChildren />
    </div>
</composite:implementation>

</html>

This works.

Tuukka Mustonen