Skip to main content

Custom Control Design Definition Tricks

I think by now many people are aware of the Design Definition you can set when creating a custom control. Here is a quick refresher if you are not. A design definition simply replaces what you see when you drop the control on an xpage. By default, it shows whatever is in your control, but this property can be used to replace that with:
  • documentation about how to use the control, for example what custom properties mean or other requirements such as using a data source named "document1"
  • A visual short-hand, for example a control could just show <Header Control> instead of everything inside. This is great for minimizing clutter in the designer and it can also speed up the loading/rendering of the xpage in designer.
  • An interactive tool that allows you to drop additional controls inside
 There are a couple of advanced features that can be tricky to figure out unless someone shows you. Here is one:


Setting label text dynamically

If you drop a label and an edit box into a custom control, you can set what they look like through the design definition. For example you could display it this way:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:table>
      <xp:tr>
        <xp:td>fieldLabel</xp:td>
    <xp:td>
          <xp:inputText
            value="dataSource"
          >
          </xp:inputText>
        </xp:td>
      </xp:tr>
    </xp:table>
</xp:view>
The problem with doing it this way is once you drop a few of these controls on your document, you can't tell one from another without looking at the custom properties of each. There is another way of doing this using JSP expressions. By changing the definition a little bit, we can dynamically set the display text of the custom control so that we can identify one instance of a control from another:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:table>
      <xp:tr>
        <xp:td>
          <%=this.labelText || 'Label'%>
        </xp:td>
    <xp:td>
          <xp:inputText
            value="<%=this.bindTo || 'DataSource'%>"
          >
          </xp:inputText>
        </xp:td>
      </xp:tr>
    </xp:table>
</xp:view>
I'd like to find a way to edit these properties directly on the custom control at some point, just to make this a little easier and more fool-proof, but for now I'm satisfied with just being able to do this at all.

One caveat I have found is that this doesn't seem to work when you are using property groups. When I tried to do something like value="<%=this.input1.bindTo || 'DataSource'%>" designer kept complaining that input1 is null.

Comments

Popular posts from this blog

Pass data between XPages and existing LS scripts

I'm working on modernizing a fairly hefty application with a lot of existing script libraries which we want to leverage within the XPages environment. Here is a technique that works very well. First, create an in-memory document in SSJS. We can set any input values needed for the back end. Then we pass that document to a LS Agent which can work it's magic using the values set in SSJS and use the same document to return values back to the XPage. Here is how it works in detail:

Quick tip: Convert a number to String in EL

I just had a need to do this and a Google search didn't immediately turn up a solution. So I thought for a couple of minutes and came up with this: value="0#{numberVar}" This takes advantage of the way Java auto-converts objects to strings when doing a concatenation. So if your number is 13, Java EL turns this into new String("0"+13), which becomes "013". You can then strip off the leading zero or just parse the string back into a number.

Project in Review - Part 3: What didn't work

Of course, not everything was an unmitigated success. I tried many things that didn't work out. Much of which I've removed and forgotten about, but a few things remain - either scarred into my psyche or woven too deeply to fix. What didn't work Storing my entire configuration in application.properties Using properties files is great. It let me get configuration out of a profile document and into something much easier to edit - particularly configuration that users will never see or maintain (and thus there is no need for an interface for). But I took it too far. The paths to the other databases are there, and that's good. But view aliases are also there, and that was a mistake. I already have a ViewDefinition enum that describes each view and all the information I need to know about it. I could have set view names there, but instead I'm reading them from the application config. I can change where a view is pointing without having to go into my code. Except of co