XPages Tip: Fixing the Display of ComboBoxes in Read Mode with Dojo

There’s a quirk with the display of combobox values when XPages are in read mode. Instead of just displaying the value, it generates a table with one row and one cell. This can cause problems with your form alignment if your fields are aleady in a table (especially a OneUI form layout table). This post contains a few lines of dojo code that can be used to fix the problem.

If you have a one-row two-cell table that contains a label and a combobox, it looks like this in the page source in Domino Designer:

<table>
  <tr>
    <td>
      <xp:label value="Label" id="label1" for="comboBox1"></xp:label>
    </td>
    <td>
      <xp:comboBox id="comboBox1" value="#{document1.Field1}">
        <xp:selectItem itemLabel="Value 1"></xp:selectItem>
        <xp:selectItem itemLabel="Value 2"></xp:selectItem>
        <xp:selectItem itemLabel="Value 3"></xp:selectItem>
      </xp:comboBox>
    </td>
  </tr>
</table>

But this is the output in read mode:

<table>
  <tr>
    <td>
      <label id="view:_id1:label1" for="view:_id1:comboBox1" class="xspTextLabel">Label</label>
    </td>
    <td>
      <table id="view:_id1:comboBox1">
        <tr>
          <td>Value 1</td>
        </tr>
      </table>
    </td>
  </tr>
</table>

Instead of just writing out the value of the combobox, it wraps it in a table.

(A regular field value is generally written out within a span tag that has the id of the control.)

When the combobox doesn’t have a value, then an empty table is inserted (no rows or cells):

<table id="view:_id1:comboBox1"></table>

This code, when run onClientLoad of the page, will fix this issue by replacing the table with just the value of the combobox.

if("#{javascript:document1.isEditable()}" == "false"){
  // Search for all nested tables with ids
  dojo.query('table td table[id]').forEach(function(node) {
    var value = '';

    // Locate the first table cell, which contains the value
    dojo.query('td:first-child', node).forEach(function(innerNode) {
      value = innerNode.innerHTML;
    });

    // Replace the table with only the value (or a blank)
    node.outerHTML = value;
  });
}

Line 1 tells it to only run in read mode. (Update the name of the document data source variable if you need to.)

Line 3 gets a handle on tables with ids that are nested inside of table cells.

Lines 7-9 search for the first cell within the table and retrieve it’s innerHTML, which is the value of the combobox. If there is no value, then there won’t be a table cell and it will replace the table with an empty string.

Line 12 replaces the original combobox table with just the value that needs to be displayed.

And now the output from the example shown above looks like this, as it should:

<table>
  <tr>
    <td>
      <label id="view:_id1:label1" for="view:_id1:comboBox1" class="xspTextLabel">Label</label>
    </td>
    <td>
      Value 1
    </td>
  </tr>
</table>

If you run into conflicts with this affecting other tables in your page, you may need to refine the selector in line 3.

If you need to preserve the of the element and/or wrap it in a span tag like other field values, you can tweak the code accordingly.

Advertisements

4 responses to “XPages Tip: Fixing the Display of ComboBoxes in Read Mode with Dojo”

  1. Naveen says :

    Another approach can be to use custom renderers which completely remove the table tags from the generated output. I blogged about it here http://www.pipalia.co.uk/xpages-2/creating-custom-renderers-for-xpages-controls/. It is a bit tedious solution but once you get your hands on it, it does a pretty good job 🙂

    • Brad Balassaitis says :

      Absolutely! Even tried that first (and it worked), but the application that I’m working on now requires multilingual support, so more code would have been required to handle the translated value. I took this approach to keep it simpler. Love the idea of customizing the renderers in general — I’m sure there are many great use cases for it!

  2. Tim says :

    Does this work with repeat controls?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: