Your Development & Design Resource

Creating an application framework for XPages using Custom Controls

Most web applications retain a consistent layout throughout the user experience story. In fact, it's actually bad practice (with few exceptions that all but define the rule) to switch up the user experience specific to application layout.

Simply put, if you start the user with a form that has buttons that run across the top of the application (an action bar, for example, in the form header), another form that has it's action bar positioned in the form footer is going to stick out like a sore thumb.

As application developers (and often designers), it's our job to not only deliver excellent functionality, but also an intuitive and consistent user experience and interface.

Luckily, IBM XPages give us a rather easy to implement and certainly easy to maintain solution: Custom Controls!

The design element correlation between a traditional Lotus Notes Domino Subform and an XPage Custom Control is slightly off the mark.

Sure, a Custom Control can contain a subset of a form -- something like shared, hidden fields that need to be saved across multiple forms in your XPage applications -- but Custom Controls give us functionality that will break your brain if you continue comparing them explicitly to Subforms.

A Custom Control can have an Editable Area.

From the Domino Designer 8.5.3 Help:

Editable areas are regions that users can modify when the custom control is placed on an XPage. All other regions that fall outside of editable areas are read-only and cannot be modified.

OK, I'll admit that really doesn't help. But I'm more of a descriptive pseudocode example + some pretty pictures-person, so perhaps this will help explain it to those of you like me who read that help text and swooned from a hypertension buzz:

Let's say we create a new Custom Control named "cc_layout". This control will act as the default layout for our XPages -- be they a form or a view -- and will be designed to be used across multiple applications. In other words, it's a simple yet functional shell that we can extend per XPage app to meet individual needs.

The desired goal for "cc_layout" is to have a left-handed, collapsable menu with the real content of our XPage sitting in a large pane.

'cc_layout.xsp' Custom Control Mockup - Expanded Settings Menu 'cc_layout.xsp' Custom Control Mockup - Expanded Settings Menu

'cc_layout.xsp' Custom Control Mockup - Collapsed Settings Menu 'cc_layout.xsp' Custom Control Mockup - Collapsed Settings Menu

If I wanted to do this with IBM Lotus Notes Domino using traditional design elements, I would have to (and have had to) create one subform that housed the beginning of the markup and another that housed the ending of the markup.

You'd get something that looked like this:

Screencap: HTML Markup Subforms for Screencap: HTML Markup Subforms for

Y'know, I really gotta find the time to redesign this site...

Well, as you can tell, this technique of wrapping beginning and end-tag HTML markup via Subforms will certainly get the job done... but that simply won't work with XPages.

First, you can't leave a pass-thru markup tag open in XPage XSP markup. The editor will bark, the builder will throw errors, etc.

Second, and quite frankly the whole point of this article: XPages offers a much better way:

'cc_layout.xsp' Custom Control Mockup - Editable 
Area overlay 'cc_layout.xsp' Custom Control Mockup - Editable Area overlay

Let's [finally] take a look at our "cc_layout".

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xp:view
  3.     xmlns:xp=""
  4.     dojoTheme="true"
  5.     dojoParseOnLoad="true"
  6.     xmlns:xe=""
  7.     xmlns:xc="">
  9.     <xp:this.resources>
  10.         <xp:styleSheet
  11.             href=" ources/ExpandoPane.css">
  12.         </xp:styleSheet>
  13.         <xp:dojoModule
  14.             name="dijit.layout.ContentPane"></xp:dojoModule>
  15.         <xp:dojoModule
  16.             name="dijit.layout.BorderContainer"></xp:dojoModule>
  17.         <xp:dojoModule
  18.             name="dojox.layout.ExpandoPane"></xp:dojoModule>
  19.     </xp:this.resources>
  21.     <xp:div
  22.         id="container_main"
  23.         dojoType="dijit.layout.BorderContainer">
  24.         <xp:this.dojoAttributes>
  25.             <xp:dojoAttribute
  26.                 loaded="true"
  27.                 name="gutters"
  28.                 value="true">
  29.             </xp:dojoAttribute>
  30.             <xp:dojoAttribute
  31.                 loaded="true"
  32.                 name="design"
  33.                 value="sidebar">
  34.             </xp:dojoAttribute>
  35.             <xp:dojoAttribute
  36.                 loaded="true"
  37.                 name="liveSplitters"
  38.                 value="true">
  39.             </xp:dojoAttribute>
  40.         </xp:this.dojoAttributes>
  42.         <xp:div
  43.             id="container_menu"
  44.             themeId="container_menu"
  45.             dojoType="dojox.layout.ExpandoPane"
  46.             title="#{javascript:@DbTitle()} Settings">
  47.             <xp:this.dojoAttributes>
  48.                 <xp:dojoAttribute
  49.                     loaded="true"
  50.                     name="splitter"
  51.                     value="true">
  52.                 </xp:dojoAttribute>
  53.                 <xp:dojoAttribute
  54.                     loaded="true"
  55.                     name="region"
  56.                     value="leading">
  57.                 </xp:dojoAttribute>
  58.             </xp:this.dojoAttributes>
  59.             <xc:cc_menu />
  60.         </xp:div>
  62.         <xp:div
  63.             id="container_content"
  64.             themeId="container_content"
  65.             dojoType="dijit.layout.ContentPane">
  66.             <xp:this.dojoAttributes>
  67.                 <xp:dojoAttribute
  68.                     loaded="true"
  69.                     name="splitter"
  70.                     value="true">
  71.                 </xp:dojoAttribute>
  72.                 <xp:dojoAttribute
  73.                     loaded="true"
  74.                     name="region"
  75.                     value="center">
  76.                 </xp:dojoAttribute>
  77.             </xp:this.dojoAttributes>
  78.             <xp:callback
  79.                 facetName="container_content"
  80.                 id="container_contents">
  81.             </xp:callback>
  82.         </xp:div>
  84.     </xp:div>
  86. </xp:view>

That's a lot to digest -- so let's review:

I'm using the Dojo BorderContainer, ContentPane, and the ExpandoPane to create my basic shell. The AccordionContainer is actually in the "cc_menu" Custom Control (line 59). But none of that is really important. Pay attention to lines 78-81:

[Abstracted from the above example for highlighting purposes]


This callback XSP tag is the Editable Area of your Custom Control.

Let's see how it's used in our "Home.xsp" XPage before we continue:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xp:view
  3.     xmlns:xp=""
  4.     xmlns:xc="">
  6.     <xc:cc_layout>
  7.         <xp:this.facets>
  8.             <xp:div
  9.                 xp:key="container_content">
  10.                 <h1>Home Page Content Here</h1>
  11.             </xp:div>
  12.         </xp:this.facets>
  13.     </xc:cc_layout>
  15. </xp:view>

The "cc_layout" will allow you add any control node (eg., xp:span, xp:div>, etc.) as a facet. As long as the xp:key matches the Editable Area facetName, it will display in the appropriate place!

This is, by far, not a new concept. If you look at the XPages Framework or the Extension Library's "ApplicationLayout" Control, you'll see it uses facets to allow you to customize the in-application specifics while maintaining a consistent user interface and experience throughout your XPage applications.

Something you should consider though: If you write your own layout Custom Control and establish standard naming conventions for your facets, you could rather easily swap out a new/updated layout for your entire application by modifying a single Custom Control! Simply rename "cc_layout" to "cc_layout_old", add your new "cc_layout", and rebuild the NSF.

For those of you wanting to see an online demo -- which I'll admit does not have the same punch that my other recent online demos have had lately -- check out .

And before anyone asks, this layout will be used in an upcoming demo. I wanted to get this concept out of the way before I introduce the stuff in this demo that I've been working on between technical editing a book, working on customer projects, raising 5 kids...

More on that (the demo, not my insane schedule) soon!

About the author: Chris Toohey

Thought Leadership, Web & Mobile Application Development, Solutions Integration, Technical Writing & Mentoring

A published developer and webmaster of, Chris Toohey specializes in platform application development, solutions integration, and evangelism of platform capabilities and best practices.

More from is powered by IBM Notes Domino XPages & hosted by Prominic.NET

Contact Us

Use our Contact / Feedback form or one of these email addresses:

Creative Commons License

Except where otherwise noted, by Chris Toohey is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.