In XPages, you can compute the value binding of an input control. In this post, I’ll show how to use the powerful capability in order to streamline your design by creating custom control that allows you to reuse a field as needed for consistency, flexibility, and ease of maintenance.
A Simple Use Case
A simple use case for this functionality would be a survey application where forms could consist of many questions with similar sets of options for a response. Rather than creating the same combobox or radio button group over and over, you could have a single field designed as needed and reused for all questions that require the same options.
This would be especially useful if you develop dynamic form-building capability that allows users to specify any number of questions and build the form on the fly.
Advantages of this Design Pattern
There are several advantages to modularizing the design in this way, rather than creating several instances of a field with the same design over and over.
- Easy to reuse
- Easy to maintain list values, styling, etc
- Easy to maintain more complex functionality (event handling code, validation/error handling)
- Ability to bind the field to a document data source or some other data source
Creating the Reusable Field Custom Control
1) Create a custom control and add custom properties
Create a property for the field name / object property name. This will define where the data will be stored. This property is a string.
Create a property for the data source. This step isn’t required if you just want to assume the data source name (e.g. if all fields will be stored on document1), but it allows you to make the custom control much more flexible.
Set the property type to be a data source. Click the folder icon next to the Type field, expand Data Sources, and select dataInterface.
You can set the Editor to be a Data Source Picker, but it doesn’t quite work the way you’d expect, so it’s not necessary. (Explanation below.)
2) Add the reusable field and set its value binding. In this case, I have a combobox with 5 standard rating values that will be reused throughout the page.
<xp:comboBox id="comboBox1" value="#{compositeData.dataSource[compositeData.Rating_FieldName]}"> <xp:selectItem itemLabel="Strongly Agree"></xp:selectItem> <xp:selectItem itemLabel="Mildly Agree"></xp:selectItem> <xp:selectItem itemLabel="Neutral"></xp:selectItem> <xp:selectItem itemLabel="Mildly Disagree"></xp:selectItem> <xp:selectItem itemLabel="Strongly Disagree"></xp:selectItem> </xp:comboBox>
The Power of EL
The computed value binding for the field in line 2 above is what makes this flexible design pattern possible. It combines the flexibility of XPages (allowing dynamic value bindings) with the power of Expression Language in order to define a value binding that is flexible enough to work with multiple types of data sources.
The EL syntax of dataSource[propertyName] will evaluate for an object property as well as a document field name!
compositeData is the object that provides the handle to all property values passed into a custom control, so compositeData.dataSource evaluates to the data source that is passed in. compositeData.Rating_FieldName is the property for the name of the field to which the value will be bound.
Using the Custom Control
Here’s an example of the source of an XPage that will use 3 instances of the field. In each case, it passes in the same data source but a different field name.
Question 1: <xc:ccDynamicallyBoundField dataSource="#{javascript:return document1;}" Rating_FieldName="Field1"> </xc:ccDynamicallyBoundField> <xp:br></xp:br> Question 2: <xc:ccDynamicallyBoundField dataSource="#{javascript:return document1;}" Rating_FieldName="Field2"> </xc:ccDynamicallyBoundField> <xp:br></xp:br> Question 3: <xc:ccDynamicallyBoundField dataSource="#{javascript:return document1;}" Rating_FieldName="Field3"> </xc:ccDynamicallyBoundField>
Passing the Data Source
I mentioned earlier that you can set up the data source custom property of the custom control to be a data source picker (screen shot above shows it), but that it doesn’t work as expected.
It appears to work in that it lets you choose from a list of data sources on the page, but it does not actually work to pass the data source! It essentially passes a string with the name of the data source. The property looks like this:
dataSource="document1"
Instead, you need to compute the property that’s being passed to the custom control to return the data source:
return document1;
This sets the property passed to the custom control as shown in the code snippet that uses the custom control earlier in this post.
I’ve tested this with a document data source as well as a JSON object data source.
Up Next
In the next post, I’ll describe another use case and show how to extend this functionality a bit.
