Custom properties are extremely useful for modular design and reuse by sending custom values into each instance. There are a number of data types that can be selected, but no obvious way to pass an array value. In this post, I’ll describe the issue and how to work around it.
Custom Property Data Types
The default data type for a custom property is
There are a number of primitive data types available in the dropdown:
String Data Type
In this case, I want a property that can accept an array of values.
To test this, I created a simple custom control with two properties,
objectProperty, to test how they handle arrays. They both default to
string as the data type.
You can leave the data type as
string, but compute an array to return. It won’t throw an error, but it will treat it like a single string.
No Data Type
You can remove the data type from the property definition and it won’t throw an error on the custom control. However, that is not a valid property, so its treated as though that property doesn’t exist.
If you’ve already set up an instance of the custom control and passed a value to it, it will throw an error on the custom control instance: Unknown property this.. It is not defined on tag .
Custom Data Type
Fortunately, there’s a really simple solution — you can manually type in a property type.
If you type in
object as the type, it does the trick. (It effectively works as desired, although it actually accepts the data as
If you need to read a property on a custom control and do something to any component on the page before a page loads, it can get tricky because the
compositeData object is not available in the
beforeRenderResponse event and
getComponent() does not work in the
I have an application where I need to dynamically inject components before a page loads. However, the injection depends on custom properties on a custom control, so it needs to read the properties and then get a handle to a component and modify it. Since the
compositeData object isn’t available in the
beforeRenderResponse event and
getComponent() doesn’t work in the
beforePageLoad event, there’s no single place to put the code that I need.
Fortunately, there’s a simple workaround. Code in the
beforePageLoad event can read custom properties from the
compositeData object and store them in
viewScope variables. Then, code in the
beforeRenderResponse event can read those values from
viewScope and use
getComponent() to get the handle to the component that I need to modify.
In this session at MWLUG 2015, Paul Calhoun and I dug into a number of features already available in XPages, but not as widely used.
We only had time to cover half of the sections, but the full set of slides is available here
- Application Responsiveness (primarily JSON RPC)
- SSJS Tips
- Modifying Component output
- Java Tips
- Custom Controls (including dynamic field binding to make reusable fields)
- Resources for learning more
- Debugging Tips
- Event handlers
I came across an interesting quirk when defining custom properties within a custom control — there are some names that cannot be used.
While working on a reusable control for charting functionality, I wanted to add a custom property called chartTheme. As I started to type the name, it let me type ‘cha’, then prevented the ‘r’ from working. I initially thought something was wrong with the key on my keyboard, because it let me type other characters. After fiddling with it for a moment, I realized that it just refused to allow the property to be named ‘char’.
To work around it, I typed the ‘t’ next and then added the ‘r’ afterwards. (After the word ‘chart’ was in the field, it would not let me delete the ‘t’, which would have changed the word back to ‘char’.)
I tried other data type names and found a similar issue. Then I tried other keywords (true, class, etc) and got the same result.
It looks like a limitation on reserved words in Java in general. (Logically, this makes sense because everything is compiled down to Java.)
I found tested these reserved words and tested them all and verified that they are cannot be used:
I also noticed that ‘con’ and ‘nul’ are not allowed.
This can be annoying when typing a property name, but it’s easily worked around by adding a different character and then fixing it.
I’m curious to hear if you’ve had similar experience.
1. Are there any other words that you’ve come across?
2. Are there other places where you’ve seen this limitation?
If you’ve used custom properties, then you’re aware that the
compositeData object provides access to those properties within the custom control. However, you can also access those properties from outside of the custom control. In this post, I’ll show how.
Accessing a Custom Property from Within a Custom Control
Let’s start with a custom control named
myCC that has a custom property named
myProperty. Here’s what it looks like to include it on an XPage and pass in a value of myValue:
On the custom control, you can refer to that value as
compositeData.myProperty. Here’s an example of a computed field that displays the property value.
Accessing a Custom Property from Outside of a Custom Control
If you have a need to access the a value passed to a custom property of a custom control from outside if the custom control, there are two steps to take:
- Add an id to the custom control instance on the page (so you can refer to it)
- Get the custom control component, retrieve a map of its property values, and then access the property that you need
Here’s an updated example of the custom control implementation on the XPage, with an id attribute added.
<xc:myCC myProperty="myValue" id="ccID"></xc:myCC>
Here’s how to refer to the custom property from the XPage:
This concept will work fine with multiple instances of the same custom control within a page because each instance would be required to have its own unique ID.
A Use Case
Here’s an example where I’ve recently found this useful. I have an application where I have a flexible grid custom control that takes a parameter with the URL for a REST service to supply the data. When I execute a search, I don’t want to reload the entire page — I just want to call the REST service to get the updated results and apply them to the grid.
But the search field exists as part of the application layout, so it’s outside of the grid custom control. Since the grid control is used for several types of grids, the REST service will vary, so I need to read a custom property of the custom control from another place on the page. This allows the Search feature to be reusable like the custom control.
To get a custom property from a custom control, you can use the compositeData object. It automatically provides a handle to all custom properties passed to the custom control.
To get a custom property named myProperty in SSJS, you would use this statement:
var x = compositeData.myProperty;
Make sure it’s within an xp: tag
My first NotesIn9 episode has been posted: Jailbreak Your XPages View Columns
In the episode, I talk about several ways to enhance the output of columns in a view panel, which, by default, just displays text from an underlying view column. Fortunately, there are several options to customize it:
- Computing a column value with SSJS
- Passing HTML through a view column
- Hijacking a view column to take complete control of its output
There are demonstrations of hijacking a view column output by displaying an iFrame within a view column as well as rendering a dojo chart within each row, reading data from the underlying documents and using it to generate the chart with client-side dojo code.
Please take a look and let me know what you think.
And if you’ve ever considered contributing to NotesIn9 — go for it! David Leedy is a pleasure to work with and he provided all the information that I needed to make this happen as easily as possible.