In Ya Facet!

Using Facets in XPages is very nice, because it gives you an easy way for a global design of your application (and much more). It can be used in all XPages and their custom controls. The xp:callback element defines a section, and this section can be filled in by the parent component with the xp:key attribute.

Take a look at this custom control:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" style="margin: 16px;">
   <xp:text escape="true" id="computedFieldTitle"
        value="#{javascript:compositeData.title}" tagName="h1" />
   <xp:callback facetName="TabAreaCallback" id="callbackTabArea"
        xp:key="TabAreaCallback" />
</xp:view>

It has a single callback area (I will never understand why it is called „Editable Area“ in the DDE), and a xp:text which is filled in with the value of the property title of the custom control.

This CustomControl (ccFacet) can now be used in another custom control (ccMain) by using the xp:key attribute:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
   xmlns:xc="http://www.ibm.com/xsp/custom">

    <xc:ccFacet title="Hello World!" >
        <xp:this.facets>
            <xp:div xp:key="TabAreaCallback">
                <p>Hello World!</p>
            </xp:div>
        </xp:this.facets>        
    </xc:ccFacet>

</xp:view>

The <xp:div> element calls the facet of the embedded custom control back (with the xp:key as the phone number), and the content of the calling component will be inserted in the defined placeholder. Added to a XPage the result looks like this:

If you change now the design in the ccFacet, the design will be changed on every XPage automatically. Or you can add new buttons, footers, etc. which will be automatically used in all other XPages which are using the custom control.

OK? OK!

But  what will happen if we are using the compositeData object?

Let’s add the property „foo“ to the ccMain custom control:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
   xmlns:xc="http://www.ibm.com/xsp/custom">

    <xc:ccFacet title="Hello World!" >
        <xp:this.facets>
            <xp:div xp:key="TabAreaCallback">
                <p>Hello World!</p>
                <xp:text escape="true" id="computedFieldFoo"
                                        value="#{compositeData.foo}" />
            </xp:div>
        </xp:this.facets>        
    </xc:ccFacet>

</xp:view>

The custom control definition in the XPage is changed to this…

<xc:ccMain foo="bar"></xc:ccMain>

… but in the browser you will see nothing:

If you remove the ccFacet definition from ccMain, you will see that the compositeData works as expected:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
   xmlns:xc="http://www.ibm.com/xsp/custom">

<!--    <xc:ccFacet title="Hello World!" >-->
<!--        <xp:this.facets>-->
            <xp:div xp:key="TabAreaCallback">
                <p>Hello World!</p>
                <xp:text escape="true" id="computedFieldFoo"
                                       value="#{compositeData.foo}" />
            </xp:div>
<!--        </xp:this.facets>-->        
<!--    </xc:ccFacet>-->

</xp:view>

What happened to the compositeData object? Is it broken? No, it is still working correctly and refers to the compositeData of the current custom control – but the custom control is no longer the same. It The elements added to the callback have moved to another node in the component tree, and that’s why the compositeData cannot be found anymore (see here for some details).

If you print the client id of the component and the variable in the beforePageLoad event to the console, you will see the id of the custom control:

But if you take a look in the generated source of the XPage, you will see that the client ids of the elements have been moved a node deeper in the tree:

<span id="view:_id1:_id2:_id3:callbackTabArea:computedField1" class="xspTextComputedField"></span>

If you want to use the data from the compositeData object, you have to add all the properties to the ccFacet too (and create the property in the custom control):

<xc:ccFacet title="Hello World!" foo="#{compositeData.foo}">

That’s a really annoying and reduces the usability of compositeData – but it seems to be the only usable workaround for this problem.

Dieser Beitrag wurde unter Allgemein, JSF, XPages abgelegt und mit , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

4 Kommentare zu In Ya Facet!

  1. Very interesting. Thanks for the great explanation.

  2. jjtb somhorst sagt:

    I noticed the same behaviour just yesterday while working on an xpages project. Thank God I’m not the only one noticing this behaviour.

  3. To be honest, i hardly never could get facets to work (at least in my use cases..).

    It seems that the callback tag ist simply ignored within xe:dialog controls..

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.