When you're setting up a Custom Control, you likely know by now that you can set up callback areas to add content to a specified place inside your CC content when it's rendered. They typically look something like this:
<?xml version="1.0" encoding="UTF-8"?> <xp:view xmlns:xp="http://www.ibm.com/xsp/core"> <h1>Content Above</h1> <div> <xp:callback facetName="content" id="callback1"/> </div> <h1>Content Below</h1> </xp:view>
You then drop content in there like so in your XPage:
<xc:someControl> <xp:this.facets> <xp:text xp:key="content" value="foo"/> </xp:this.facets> </xc:someControl>
That works fine. However, you can benefit greatly by learning that both properties of the callback are optional.
Leaving off the
id isn't particularly interesting, but there's a small benefit: removing it means that the callback doesn't generate a
<div/> element in the resulant HTML.
Leaving off the
facetName, however, is very valuable indeed. When you do that, the callback becomes the target for any non-facet child controls of the CC, in JSF parlance. To wit:
<xc:someControl> <p>foo bar</p> </xc:someControl>
Much cleaner. And you can continue to use other callbacks with names in the control, much like you normally would:
<xc:someControl> <xp:this.facets> <xp:text xp:key="header" value="Some header text"/> </xp:this.facets> <p>foo bar</p> </xc:someControl>
The syntax ends up mirroring standard controls like
<xp:repeat/>, where the primary content area has no special name, but there are still facets available like "header" and "footer". It also saves you a valuable indent level or two, which can go a very long way to keeping your code readable.
A footnote about my in-practice use of this:
The primary way I use this technique is my "layout" control. Like with most people's apps, that control contains the main page structure (which I used to do as
applicationLayout, then switched to Bootstrap-friendly HTML, and then switched back to
applicationLayout with custom renderers). Regardless of the implementation, the layouts always have a main content callback and then one or two "column" callbacks. The XSP for the actual control changes a bit per app, but the Design Definition (which you should use) is consistent:
<?xml version="1.0" encoding="UTF-8"?> <xp:view xmlns:xp="http://www.ibm.com/xsp/core"> <xp:table style="width:100.0%"> <xp:tr> <xp:td colspan="3" style="background-color:rgb(225,225,225)">Header</xp:td> </xp:tr> <xp:tr> <xp:td style="width: 200px"><xp:callback facetName="LeftColumn" id="callback1"></xp:callback></xp:td> <xp:td> <p><xp:callback id="callback2"/></p> </xp:td> <xp:td style="width: 200px"><xp:callback facetName="RightColumn" id="callback3"></xp:callback></xp:td> </xp:tr> </xp:table> </xp:view>
(Note: never write code that looks like that when it's not for a Design Definition)
With that, I get a nice, clean, performant table in the WYSIWYG editor with drop targets for each control. I don't use the WYSYWIG editor (and neither should you), but it helps to have that when I open the page initially and it cuts down on crashes. In any event, using it on a page is much like above:
<xc:layout navigationPath="/Home"> <xp:this.facets> <xc:linksbar xp:key="LeftColumn" /> </xp:this.facets> Stuff goes here </xc:layout>