Archive | Computed When Composed Fields RSS for this section

Computed When Composed Fields in XPages

One of the first conceptual lessons we learn in XPages is that a Computed Field control does not provide the functionality of all variations of a Computed Field in the Notes client — it’s really analogous to a Computed for display field. However, we can still approximate the rest of the Computed Field functionality with a little bit of understanding of how it needs to work.

Mapping Notes Client Field Types to XPages

Along with specifying a field’s data type in the Notes client, you have 4 options for the field type: Editable, Computed, Computed for display, Computed when composed.

Here’s how they map to XPages core controls:

Notes Client XPage
Editable Edit Box
Computed Computed Field (and set the value via code as the document is processed)
Computed for display Computed Field
Computed when composed ???

To approximate a Computed field, we just need to have a Computed Field control bound to a document field and add code that sets the field value when the document is saved (or at any other point while processing the page).

Computed When Composed Field Requirements

Computed when composed fields are a bit trickier. They need to meet the following criteria:

  1. The value must be set before the page is rendered
  2. The value must be available for other fields to reference as the page is rendered
  3. The value must only be set when the page is first created (and not re-computed)

We know that it will need to use a Computed Field control, but the trick is how and when to set the initial value so that it truly is computed when the form is composed. For example, if you have a form that displays certain fields based on a ‘Type’ value, that value will need to be set before a new document loads, so the hide formulas can compute based on it.

A Couple of (Less than Ideal) Options

One option is to create hidden editable fields and set their default values and then create corresponding Computed Field controls to display them. This way, the values are computed one time, but still not editable on the front end.

Another option might be to set the Computed when composed field on the underlying form and use the compute with form option. Aside from the fact that you probably just died a little on the inside at that suggestion, it’s just not good design to have to maintain logic on the underlying Notes client form if you don’t have to.

A Better Option

The best method that I’ve found has these two steps:

  1. Add a Computed Field control and bind it to the underlying form field
  2. Use code on the beforePageLoad event to set the value on the document if it is new

Here’s a simple snippet of code that you can run on the beforePageLoad event:

if (document.isNewNote()) {
  document.replaceItemValue(fieldName, newValue);
}

This sets the value of the field on the document and allows other fields to be rendered or computed based on it.

Timing is (almost) Everything

It is important to note that the timing is very important in this working properly. The beforePageLoad event allows the values to be set early enough in the JSF life cycle that they are available before the page is generated and rendered to the browser. It does not work on the beforeRenderResponse event. I believe this is because the JSF component tree has already been built and components already have their values by this time, so it’s too late in the life cycle to allow other fields to be rendered based upon it.

For more information, see Peter Presnell’s informative post on the order of events firing when an XPage is loaded.

Paul Withers has also written a great explanation of the JSF life cycle.

Be careful to use the XSP Document

I have most recently used this technique successfully with the replaceItemValue() method of the XSP document, as shown in the code snippet above.

document.replaceItemValue()

I’ve had other code that set values on back-end documents by getting a handle to the underlying document.

document.getDocument().replaceItemValue()

The latter did not work well with the implementation of computed when composed fields for two reasons:

  1. The values showed up on the form and appeared to work fine, but they were not actually saved to the back-end document, so I had to write code when saving to store them again. When the XSP document is saved, the values on the XSP document overwrite what’s on the underlying document.
  2. Even though the values displayed on the page, they weren’t available to the page processing logic, so they didn’t work when rendered formulas were evaluated.

Alternate Solutions?

This being XPages, there are always many ways to solve the same problem.

What other ways have you dealt with Computed when composed fields?

Advertisements