Accessing the Value of Components within a Repeat Control from Outside

As a general rule, XPages variable resolution makes it very easy to access components within the same instance of a repeat control, but very difficult to access a component that’s within a repeat control from outside of it. In this post, I’ll show you you can configure the repeat control and define component IDs in a way that you can access them from outside of the repeat control.

1. Set the “Create Controls at Page Creation” Property

By default, the JSF component tree only includes one copy of each component in for the repeat control and it iterates over it as many times as needed to generate each instance of the repeat. I’m not aware of a way to access an individual instance of a component this way.

This is where the Create controls at page creation property of a repeat control comes into play. This property adds the repeatControls attribute to your repeat control tag and sets it to true. When enabled, it causes an instance of each component to be created for each instance of the repeat control in the JSF tree.

RepeatControls

Update: Read about the side effect of enabling this property so you understand the effect it could have on your application.

2. Dynamically-Assign Component IDs Based on the Repeat Index

In order to access a specific control within a specific instance of the repeat, I need to know what its name is. I need to assign a unique ID to each instance of each component in order to be able to access it.

With inspiration from this great blog post by Chris Toohey (which was, in turn, assisted by Tim Tripcony), I found a way to make all of this work.

As Chris pointed out, you cannot compute component IDs dynamically, but you can compute them on page load.

By setting the Index name property of the repeat control (see screen shot above), I’ll have an index variable available for each instance of the repeat control. To create a unique name, I took the existing component name and updated it to dynamically add a suffix based on the index variable.

There’s no blue diamond to compute the ID of a component, so you have to go into the source and change it directly.

<xp:comboBox id="MyComboBox_${rptIndex}">

Now the component is uniquely but predictably named and can be accessed as needed!

Example Repeat Control Source

Here’s the source of the repeat control from my simple sample XPage. Each instance of the repeat control displays a combobox with a few hard-coded options. An array with 4 elements is passed to the repeat control in order to create 4 instances of the repeat. (The values in that array are not used at all in this simplistic example.)

<xp:repeat id="repeat1" rows="30" indexVar="rptIndex" repeatControls="true">
  <xp:this.value>
    <![CDATA[#{javascript:return ['aa', 'bb', 'cc', 'dd']}]]>
  </xp:this.value>
		
  <xp:comboBox id="MyComboBox_${rptIndex}">
    <xp:selectItems>
      <xp:this.value><![CDATA[#{javascript:return ['', '1', '2', '3', '4'];}]]></xp:this.value>
    </xp:selectItems>
  </xp:comboBox>
  <xp:br /><xp:br />
</xp:repeat>

Checking the Component Values

The code check the values within the repeat control to can be dynamic. Since I don’t know how many instances there will be when using this in a more dynamic application, I set it up to look for a component within the repeat and loop until it doesn’t exist with a next index suffix.

Here is sample SSJS code on a button on the page (outside of the repeat control) that will check the value of the combobox within each instance of the repeat control and print the value to the server console.

var i=0;
var boolContinue = getComponent('MyComboBox_' + i);
while (boolContinue) {
  print ('value ' + i + ': ' + getComponent('MyComboBox_' + i).getValue());						
		
  // Check whether there's another RCA form an determine whether to continue
  boolContinue = getComponent('MyComboBox_' + ++i);
}

Line 2 sets a boolean value based on whether the component in the first instance of the repeat control can be found. (If there are no entries in the repeat control, then the code will not proceed.)

Line 4 accesses the value of the control with the index suffix and prints the value.

Line 7 checks if there’s another instance of the control with the next suffix number and determines whether to continue based on that.

Proactive Disclaimer

I know there are some (**cough** Tim **cough) who would strongly suggest that I read data from the document directly rather than try to access the components in this way. As a general rule, I wholeheartedly agree. However, the use case that necessitated this workaround is that it’s for form validation for related documents within a repeat control and, with the method of validation I’m using, I need to access the components in order to mark them as invalid as needed.

Advertisements

7 responses to “Accessing the Value of Components within a Repeat Control from Outside”

  1. David Head says :

    Thanks! That is the solution I have been pulling my hair out trying to find.

  2. Justin Lin says :

    thanks, it is amazing way to do.

  3. Ryan says :

    I keep getting the following errors in the server log when I try to run getComponent(‘MyComboBox_’ + i);

    04/01/2014 01:56:57 PM HTTP JVM: com.ibm.xsp.webapp.FacesServlet$ExtendedServletException: javax.faces.FacesException: Error while executing JavaScript action expression
    04/01/2014 01:56:57 PM HTTP JVM: CLFAD0134E: Exception processing XPage request. For more detailed information, please consult error-log-0.xml located in d:/Program Files/IBM/Lotus/Domino/data/domino/workspace/logs

    Any ideas?

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: