SOM Expressions
The Scripting Object Model (SOM) is one of the backbones of the XFA Specification. The SOM provides a structure for referencing objects and properties in our forms.
A SOM expression is simply the reference in a script to another object. If the objects are in the same container, then the SOM expression can be as simple as the object’s name. If however, the objects are in different subforms or pages, then a fuller SOM expression will be needed.
The Scripting Object Model Expression Specification states:
XFA-Scripting Object Model (XFA-SOM) is a model for referencing values, properties and methods within a particular Document Object Model (DOM). A DOM structures all objects and properties in memory as a tree hierarchy. XFA-SOM expressions provide easy access to these objects and properties through a straightforward object reference syntax.
There are two basic types of SOM expression:
- Relative SOM expression, which references an object relative to the object containing the script.
For example “TextField1“. - Absolute SOM expression, which references an object from the root node (xfa).
For example “xfa.form.form1.page2.Subform1.TextField1“.
In most circumstances a relative SOM expression is perfectly adequate and would be the normal approach when referencing objects.
Dynamic Demonstration
We have an example form that demonstrates the various approaches to SOM expressions.
Download: Assure Dynamics SOM Expressions (v4)
When you open the form in Acrobat or Reader, you can hover over the SOM expressions in the script and the corresponding objects will be highlighted. This will help you to understand the SOM expressions.
[UPDATE] Jono Moore spotted an error in the script in the button on page 4. It was a debugging line that was not deleted. The form has been updated. Thanks Jono!
[UPDATE] John Brinkman has provided very valuable assistance in improving the performance by using xfa.resolveNodes(). Thanks John!
General Considerations
Because the SOM expression uses an object’s name, it stands to reason that the SOM expressions will be heavily influenced by how you name your objects in your forms. It is important to establish a naming convention that suits your requirements and then apply this consistently in your forms.
If you are using JavaScript, then there may be situations where you will need to resolve a node. This may happen if you have objects in unnamed containers (pages and/or subforms), or if there are multiple instances of an object with the same name.
xfa.resolveNode()
xfa.resolveNode is a search. For example, xfa.resolveNode(“TextField1″); will search for TextField1 object. The search will start in the current container and work its way up the hierarchy tree. The first occurrence of TextField1 that is found will be used. This is not an efficient way to script and there will be a performance hit. In addition it may not return the instance of TextField1 that you are expecting.
xfa.resolveNode is also used when you are referencing an object that has the same name as other objects in the same container, for example TextField1. In the hierarchy you would see TextField1[0], TextField1[1], TextField1[2], etc. The number in square brackets shows the instance number of each object. When using FormCalc you can just use TextField1[2] directly in the SOM expression.
However if using JavaScript the square brackets will be misinterpreted by JavaScript, as [] are normally used to declare an array. If in your script you want to reference TextField1[2], then you would need to resolve the node. For example, xfa.resolveNode(“TextField1[2]“);. In this scenario xfa.resolveNode() is not executing a search. It is targeting a specific instance of TextField1 and is just resolving the node so that the JavaScript interpreter can correctly interpret the reference.
This is a another good reason to name objects uniquely, as you drag them onto the form. This can eliminate the need to resolve the node.
However there are other situations when you will need to resolve nodes, for example, if you are referencing an object that is in an unnamed container/page/subform. The script needs to resolve the unnamed container in order to access the object inside. This would also apply if there are several containers with the same name. Again, another good reason to name containers as you go.
Also if you are trying to reference a particular instance in a repeating object, then you would need to resolve that particular instance.
xfa.resolveNodes()
John Brinkman’s blog clearly explains the benefits in using xfa.resolveNodes() to return a list of multiple nodes. We have extended the sample form to highlight this method.
We would strongly recommend that you read this post in particular.
Getting the SOM Expression Right!
LiveCycle Designer ES2 has a great feature, which makes it very easy to automatically insert the correct SOM expression for an object.
When the Script Editor is active, if you press and hold the Control key, you will notice that the mouse changes to a ‘V’ when it hovers over an object.
- Step 1: Select the object that you want to have script in one of its events.
- Step 2: Click into the Script Editor to make it active. Select the event that you want to script.
- Step 3: Next you hover over the mouse over the event that you want to reference in your script.
- Step 4: Press and hold the Control key. When the mouse changes to a ‘V’, you can click the object.
- Step 5: LiveCycle Designer will insert a relative SOM expression for that object. The relative reference will be as qualified as is necessary, depending on the structure of your form.
The Control and Click covers most situations. If you want an absolute reference, then you would hold Control+Shift and Click.
If LiveCycle determines that the object cannot be uniquely referenced, it will automatically use xfa.resolveNode() to resolve the node. It is worth spending a little time to correct the issue and then reinsert a relative reference without the xfa.resolveNode().
Here is a quick example of creating relative references in LiveCycle Designer:
Guides
Adobe has a number of technical reference documents that will be of help to you.
You can access the XFA Specifications here.
In order to get a fuller understanding of SOM expressions, you should read the Scripting Object Model Expression Specification.
You should also download the LiveCycle Designer ES2 Scripting Reference.
XFA Form
Be sure to check out the dynamic demonstration of SOM expressions. It contains more information on SOM expressions and how to use them correctly. We would welcome feedback and suggestions. Where we get requests, we will extend the form with additional examples.
Hi Niall,
Excellent post. I quite like the way you have made use of examples and graphics to drill in the concept.
#inspiring
However, you might be aware that XFA form variables are deprecated with ES2 and beyond, is it worth mentioning in your blog?
-
Sy
Thank you Suhas for you comments and input!
I am going to consider the deprecation of the XFAForm variable and how best to communicate this aspect. I had not fully appreciated that it had been depreciated.
Thanks,
Niall
Niall:
Great post. Very impressive sample.
I should point out that your code for manipulating fills could be more terse.
Instead of:
var vName = price.somExpression;
var fieldObj = xfa.resolveNode(vName + “.ui.#numericEdit.border.fill”);
fieldObj.presence = “visible”;
try:
price.ui.oneOfChild.border.fill.presence = “visible”;
thanks,
John
[...] a regular commenter) has written a blog post that does a great job of explaining SOM expression: http://www.assuredynamics.com/index.php/2011/05/som-expressions/. Niall has a gift for explaining the basics of the technology. The post includes a very spiffy [...]
John,
Thank you very much for pointing that out. The oneOfChild is much cleaner.
I have implemented it in the form and uploaded a new version.
Thanks,
Niall
Dear Niall,
I have been busy for two days just trying to find a way to add the total of a Column, but could not find anything usefull on any website sofar…untill I read this article.
The advise of “Control”+”Shift”+”Click” worked out well, I finally see a total, Thank you so much.
I will read your article again and also the links provided as I am sure they will be useful too.
I am just a beginner, and I am happy to have at least succeeded in completing something at the end of this day. Thanks, and happy new year 2012.
Best regards,
Ilja
You’re welcome Ilja, I’m glad the example has helped you.
There are plenty of other code solutions on the site and if you look at the resources blog, you will see other resources that I recommend.
Happy New Year,
Niall