As developers get more comfortable with XPages, one of the steps is to start to using the Compute on Page Load option instead of the Compute Dynamically option for Server-Side JavaScript. But there are times when that can’t be done. I encountered this last week and it took a chat with Jeremy Hodge for me to understand my problem. One of my colleagues had the same problem yesterday. And Sven Hasselbach has blogged about the same issue today. Unfortunately, it’s not a bug. It’s a fact of life and one also found in JSF.

 

Sven encountered the issue, as did I, in an Output Script control. Basically, if your Output Script code combine ${…} code and #{…} code, for example #{id:myField1}, the #{…} code is always evaluated at page load. This means, in the case of #{id:myField1} that it returns a blank ID. This isn’t limited to Output Script controls. It’s the same for any control, even a Computed Field.

 

One of the nice things about XPages, once you’ve mastered the basics, is the Custom language. This allows you to combine textual and computed elements in a single Value Binding, as I blogged about last July. But even in a Computed Field, you can’t combine ${…} and #{…}. Let’s put this in context.

 

Look at this code. It’s fairly basic. We’re outputting a username and control IDs.

Binding Code

But look at the output. For the first control, we get the ID. For the second, we get the username, but not the ID.

Binding Output

That’s because the ID for computedField1 has been generated at runtime, but the binding for computedField2 has been generated at page load. Basically, because we have something that needs generating at page load, everything needs running at page load.

 

This may seem strange. But if we understand what’s happening behind the scenes, it’s understandable. Any non-literal string is stored as a String and passed to a Java function. So whereas a developer might consider “${javascript:@UserName()}” as a distinct element, the XSP Command Manager just interprets the whole value property as something that needs passing to a Java method. Let’s look at the Java code outputted, and the difference becomes apparent.

 

The first control has the following Java code:

Java for computedField1

The whole value property, including the #{id:…} element is stored into a String , which is passed as a parameter to evaluator.createValueBinding() – not all parameters passed to the method are shown.

 

But compare computedField2’s Java code.

Java for computedField2

Here, again, the whole value property including the @UserName element is passed into a String. But notice it is passed in as #{…}. The ${…} serves only to tell Designer that it needs to call evaluator.getBindingValue() instead of evaluator.createValueBinding(). Because the value property is passed as a String parameter of a method, everything must use createValueBinding() or everything must use getBindingValue(). You cannot combine both, nor do I expect that you ever will.

 

Someone more knowledgeable in the intricacies of JSF can probably explain this  better than me. But the key to remember is to use #{…} or ${…}, but not both.

12 thoughts on “XPages Bindings: When # Runs at Page Load”

  1. Thanks for your explanation, but I still think that this is not JSF compliant behaviour. If you add some apostrophes to the example above, you will see that the situation is a little more complicated:

    The javascript won’t be executed anymore, but runs at page load!? If you look in the java classes, you will see, that the code is transformed like you are describing above. But this is not correct in my opinion.

    If you enter something like this, you XPage won’t get saved, the Designer tells you that there is a bad syntax:

    But not if you enter this one:

    Looks very strange to me…

    Just my two cents
    Sven

    1. Damn! The tags are not displayed.

      Here is the code w/o tags:

      1.
      … value=”you are logged in as ‘${javascript:@UserName()}’. The field id is ‘#{id:computedField1}” …

      2.
      … value=”you are logged in as ‘#{}’. The field id is ‘#{id:computedField1}” ..

      3.
      … value=”you are logged in as ‘${}’. The field id is ‘#{id:computedField1}” ..

  2. Thanks Sven. I remembered as I came into work this morning that I hit similar challenges when I was writing the Extension Library book with the queryExpr property of the Dojo Combo Box and Dojo Filtering Select. One of the options for these properties is “*${0}”. Because ${ has a specific meaning, I needed to change it to “*${0}”, so escape the {. Then everything worked fine.

  3. Paul – does this help for a work around?

    This field’s value is ${javascript:@Text(“#{id:computedField2}”)}

    You are logged in as ${javascript:@UserName()}.
    This field’s value is ${javascript:@Text(“#{id:computedField2}”)}

  4. @Marc:
    What you are doing is no longer JSF compilant.

    If you do something like this…
    ${javascript:@Text(“#{javascript:java.lang.System.currentTimeMillis()}”)}

    …and refresh the element with a partial refresh, the value is recalculated for every time. This is not what should happen if you are calculating a value on page load.

  5. @Mark:
    The “mystic” behaviour is caused by the internal handling of an expression. Please have a look at the class ‘com.ibm.xsp.util.ValueBindingUtil’. It seems to be used to identify the type of an expression. I have made some tests and think that the classes have been coded extremly – ehm – quick. F.e. by adding a blank at the end of the expression string the provided methods are returning wrong results…

    If someone at the IBM corrects this code, the code you provided would not work anymore (because it then would be JSF compliant).

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top