XPages gotcha: mode=”concat” in your themes

Suppose you have an XPage with a repeat control on it to show a list of documents. In the repeat you generate an <xp:button> for every document. Based on the status of the document you decide to give the button a different color, so you make the styleClass property of the button computed:

<xp:repeat
  id="repeat1"
  rows="30"
  var="entry">

  <xp:this.value><![CDATA[#{javascript:
    print("computing repeat value");
    return ["style1", "style2"];
  }]]></xp:this.value>

    <xp:button
      value="Label"
      id="button">
        <xp:this.styleClass><![CDATA[#{javascript:
          print("computing styleClass:");
          print( typeof entry);
          return entry
        }]]></xp:this.styleClass>
    </xp:button>

</xp:repeat>

That’s (roughly) the code you’d have to write. And guess what: it all works. Everyone’s happy!

Screen Shot 2014-08-28 at 15.35.03So you decide to enhance the looks of your application and include Bootstrap. Bootstrap requires the btn class on all buttons for styling. Being an expert XPage developer you create a theme for your application, add the Bootstrap CSS file and add a control definition to give all buttons that btn class:

<control>
  <name>Button.Command</name>
  <property mode="concat">
     <name>styleClass</name>
    <value>btn</value>
  </property>
</control>

You reload the page, thinking you’re done and guess what: errors!

That’s roughly what I’ve been looking at today and at some point thinking I lost my sanity.

The print() statements in the code above were added by me to show the order of execution. Without the <control> definition in the theme I saw this on the server console:

> computing repeat value
> computing styleClass:
> string
> computing styleClass:
> string

Exactly what I expected! But… after adding the <control> definition I saw this:

> computing styleClass:
> undefined
> computing styleClass:
> undefined
> computing repeat value

Notice the subtle, yet very important, difference in the order of computing: with the <control> definition the styleClass is computed before (!) the repeat value, making it impossible to let the button style depend on the repeat value. This behaviour is caused by the mode=”concat” part, that should combine the value of the styleClass with the one set in the theme.

The Bootstrap4XPages plugin has that same <control> definition in it, so if you’re using that you will likely run into this some day.

The solution I came up with for now is to add a new <control> definition to the theme, setting it to override any inherited settings and setting the mode to the default (‘override’). Set the themeId to the new <control> name and it all works again:

<control>
  <name>Button.NoConcat</name>
  <property>
  <name>styleClass</name>
    <value>btn</value>
  </property>
</control>

and:

<xp:button value="Label" themeId="Button.NoConcat"></xp:button>

I have no idea why it behaves this way and would have never guessed that a <control> breaks anything but the UI in my app. If anyone can share some light on this: please do!

Be Sociable, Share!

    3 thoughts to “XPages gotcha: mode=”concat” in your themes”

    1. I think it’s related to the timing of insertion for theme-based expressions. If you set repeat control as (repeatControls=”true”) and change styleClass computation to ‘$’, it should work.

      (Credits to Tim Tripcony, explained this whole mechanism in a great detail…)

    2. Great explanation of this interesting behavior.

      I came across this recently when working with alternating row style based on the index of the repeat collection. When I added the a class via the theme to concatenate the property, the page started failing when trying to refer to the repeat index in the styleClass computation script.

    Comments are closed.