Handling List Selection Changes
This is something I get asked a lot so I thought I’d write a little tutorial on how to handle a selection change in a list object (drop down list or list box).
Single Selection Lists
All XFA events have an object that represents properties about the event currently in execution:
xfa.event
This object holds many interesting properties but the one that’s important here is the newText property which, for a list, contains the new selection.
It’s important to note that there are two types of list items: Ones that have text data only and ones that have both text and value data. By default, the Object palette creates lists with items that have text data only. On the Field tab, you can add/remove items and specify their text data while on the Binding tab, you can optionally set each item’s value data by checking the “Specify Item Values” box.
The xfa.event.newText property always returns the text data. You can access the value data associated with the new text data by using the list’s boundItem() method:
// get the value data associated with the new selected text data
var newValue = MyList.boundItem(xfa.event.newText);
For single selection lists, you can therefore use the text data or get the associated value data for the new selection and do something from there. The following code sample gets the new selected value data in a list object’s Change event and changes the list’s background color accordingly:
var newValue = this.boundItem(xfa.event.newText);
switch (newValue)
{
case 1:
this.fillColor = "255,0,0"; // red
break;
case 2:
this.fillColor = "0,255,0"; // green
break;
case 3:
this.fillColor = "0,0,255"; // blue
break;
}
Multiple Selection Lists
List objects may also support a multiple selection of items. You can specify that the list supports multiple selection by setting the “Object palette > Field tab > Allow Multiple Selection” property but you cannot specify a default selection of multiple items using the Object palette (only a single default selection is supported though it still works for lists that allow multiple selections). You would have to use the list’s Initialize script to do that.
At runtime (e.g. in Acrobat/Reader), you may select multiple items in the list by using the Shift and Ctrl keyboard keys: Shift + Click will select all items from the last selected item to the item you click on and Ctrl + Click will add/remove individual (non-sequential) items to/from the selection.
Determining the selection in a multiple selection list is different from doing so in a single selection list because you have to deal with the fact that more than one item may be selected. There is also a difference in the event you must use in order to handle the change in selection: When you set the “Allow Multiple Selection” property, the “Object palette > Field tab > Commit On” property changed to allow only a setting of “Exit” (as of Designer 8.1; Designer 8.0 may have still allowed “Select” to be chosen however I recommend setting this property to “Exit” if you have the choice) which means that the change in selection — as far as the list is concerned — will only take place once the user exits the list (once they hit the Enter key, tab away or click away from the list) rather than immediately when they visually change the selection. The result is that you must handle the change in selection in the Exit Event rather than in the Change event as in single selection lists.
You can handle a change in single selection lists using the Exit event as well however for single selection lists, it’s usually preferable to handle the change immediately rather than once the user leaves the list. For multiple selection lists, the idea is that the user may click more than once to set the selection they want so you typically want to react to the change only once they’re done which is why the selection is only committed once the user exits the list.
Determining the set of selected items was really difficult leading up to Designer and Acrobat/Reader 8.0 when the new list object properties and methods were finally introduced. These new APIs make it much easier to deal with lists that contain multiple selections: Use the length property to iterate through the items, the getDisplayItem method to get the text data associated with an item, the getSaveItem method to get the value data associated with an item and the getItemState method to determine whether the item is selected or not.
Here’s our sample script from earlier that sets the background color of the list object after a change in the selection (in the list’s Change event) however this time the script is meant for the Exit event and the list supports multiple selection. The color values are combined if more than one is selected, producing more color combinations up to white (an RGB color value of “255,255,255”) then all 3 items are selected:
// array with 3 elements, all at zero initially
var rgb = new Array(0, 0, 0);
for (var i = 0; i < this.length; i++)
{
if (this.getItemState(i))
{
// item is selected
// item values are 1, 2 or 3 (1-based)
// array elements are 0, 1 or 2 (0-based)
rgb[this.getSaveItem(i) - 1] = 255;
}
}
// Array.toString() produces a comma-delimited string containing the
// values of the array elements so this will produce "255,0,255" if
// items 1 and 3 are selected.
this.fillColor = rgb.toString();
If you give this a try, remember to create a list with 3 items (1, 2, 3) and place the script in the Exit event, not the Change event. Then remember to click away from the list once you’ve set the selection at runtime.
Multiple Item Default Selection
Setting a default selection of more than one item is unfortunately not something that Designer supports. To achieve this, you’ll need to set the list’s Initialize script to do the work. For example, to initialize a multiple selection list of 5 items where items 1, 4 and 5 are selected, you would do this (remember that list item indexes are 0-based, not 1-based) in the list’s Initialize event:
this.setItemState(0, true); // item 1
this.setItemState(3, true); // item 4
this.setItemState(4, true); // item 5
Sample
To see this in action in what you might consider a more realistic example, my “What About the Other Field?” tutorial uses single selection lists that show an “other” field when their “other” item is selected.
Posted by Stefan Cameron on October 27th, 2008
Filed under Acrobat,Designer,Events,Scripting,Tutorials,XFA
Both comments and pings are currently closed.
Hi,Stefan.
I have read a lot of your blogs and google my question on the internet,but i have not found my answer yet.
I expect you can help me.
The question is how can I get the data will be submitted to Serve?I want add a signature on the data.
I have tried to use saveXML() method,but the method give me a part of XML format data, it’s not same as submitted.So if i signature on this data, it will be difficult to verify on server side.
May be I could convert the data acquired by saveXML() to be same with submitted,but it’s a lot of work to do and so complcated.
So I wonder that is there any other method to accomplish this task,get the submitted data?
Can you give me some idea?
Best Regards.
Jasper
Jasper,
The data to be submitted can be obtained by doing
If you submit your data in the XML format, that should be what gets submitted.
Thanks for your reply,Stefan.
I have already tried xfa.datasets.data.saveXML();
But it’s still the same as previous result.
The result of saveXML() is part of XML,it does not have end tag,just only start tag. And has no hiearchy of data.
Another question.
I found that each call of postMessage() method will cause a security warning dialog.
I tried to avoid this dialog in “Trust Manager”, select trust any website,but it doesnt work.How can i avoid this dialog?
Jasper,
I don’t understand how the saveXML() command could be returning bad XML. There must be a closing tag. Granted the return format may not be “pretty” but it should still be valid.
If you’re wanting to sign the data, why not just use Designer’s XML Signature feature? It’s available as of Designer 8.1.
As for Acrobat’s postMessage() function, I don’t know enough about it to tell you if and how you could bypass the security warning.