Recipe 21.5 Populating Menu Components
21.5.1 Problem
You want to use a recordset to populate a menu component instance.
21.5.2 Solution
Use the setDataProvider( ) method for
the menu component of interest. For more
complex scenarios, use the DataGlue class.
21.5.3 Discussion
List boxes and combo boxes can both be populated by recordsets
without much effort by employing one of two techniques. The first
technique is to use the setDataProvider( )
method of the list box or combo box. You can pass a recordset
reference to the setDataProvider( ) method, and
it will know how to process it. The result is that the menu displays
one item per record, with each item showing the
record's column values in a comma-delimited list.
The order in which the column values appear within each item is
determined by the order of the columns within the recordset column
names array.
#include "NetServices.as"
rs = new RecordSet(["ID", "NAME"]);
rs.addItem({ID: 24, NAME: "a"});
rs.addItem({ID: 42, NAME: "b"});
rs.addItem({ID: 66, NAME: "c"});
rs.addItem({ID: 93, NAME: "d"});
rs.addItem({ID: 33, NAME: "e"});
// Populate a list box and a combo box with the values from the recordset.
myListBox.setDataProvider(rs);
myComboBox.setDataProvider(rs);
Additionally, when you use a recordset as a data provider for a menu,
the object(s) returned by the getItemAt( ),
getSelectedItem( ), and
getSelectedItems( ) methods are record objects
instead of the conventional objects with data and
label properties. This also means that the
getValue( ) method of a menu populated by a
recordset returns undefined. Another interesting
effect of populating a menu with a recordset as a data provider is
that changes made to the recordset cause the menu to be automatically
updated.
#include "NetServices.as"
rs = new RecordSet(["ID", "NAME"]);
rs.addItem({ID: 24, NAME: "a"});
// Populate the list box with the recordset.
myListBox.setDataProvider(rs);
// Add an item to the recordset after having already set the data provider for the
// list box. The list box is automatically updated!
rs.addItem({ID: 99, NAME: "z"});
While using a recordset with the setDataProvider(
) method offers certain advantages, such as ease of use
and automatic updating of menus, it also has its disadvantages. The
main disadvantage of the technique is that you can't
control the display of the data within the menu to any great degree.
The other problem is that it doesn't conform to the
standard way in which menus work—namely, using objects with
data and label properties. The
DataGlue class offers functionality that solves
both of these problems.
The DataGlue class has two static methods
for populating UI components with
recordset data. Let's look at the first of these,
the bindFormatStrings( ) method. This method
requires four parameters:
- dataConsumer
-
A reference to the UI component, such as a combo box or a list box.
- dataProvider
-
A reference to the recordset.
- labelString
-
A string that is used for the menu labels. Any values in the string
between pound signs (#) are dynamically evaluated as column names
from the recordset.
- dataString
-
A string that is used for the menu items'
data properties. Any values in the string between
pound signs (#) are dynamically evaluated as column names from the
recordset.
The bindFormatStrings( ) method populates the UI
component with the values from the recordset and allows you to
control the label and data
values. By placing column names within pound signs (#) in the
label and data string
parameters, those values are evaluated when the menu is populated.
For example, #COL0# is evaluated for the value of column COL0 for
each record.
#include "NetServices.as"
// You must include the DataGlue.as file whenever you use DataGlue methods.
#include "DataGlue.as"
rs = new RecordSet(["ID", "NAME"]);
rs.addItem({ID: 24, NAME: "a"});
rs.addItem({ID: 42, NAME: "b"});
rs.addItem({ID: 66, NAME: "c"});
rs.addItem({ID: 93, NAME: "d"});
rs.addItem({ID: 33, NAME: "e"});
// Populate a combo box with the records from rs. The labels of each item are in the
// format NAME (ID). For example, a (24). The data properties for each item are the
// string equivalents of the ID values.
DataGlue.bindFormatStrings(myComboBox, rs, "#NAME# (#ID#)", "#ID#");
// Components populated using DataGlue methods are automatically updated as well!
rs.addItem({ID: 99, NAME: "f"});
The bindFormatStrings( ) method has a
few shortcomings. One limitation is that it
populates components only with strings, although you may want to
populate menus in which the data property is a
number, Boolean, or object. Another limitation is that it
doesn't let you manipulate the column values. For
example, if a recordset has a column PERSON_NAME
with values that are in the format FirstName
LastName, you might want to display that in the
menu as LastName, FirstName.
With bindFormatStrings( ), this is not possible.
However,
the bindFormatFunction(
) method takes care of both of these problems.
The bindFormatFunction( ) method functions
similarly to the bindFormatStrings( ) method. It
takes the same first two parameters—the data consumer and data
provider—but the third parameter for
bindFormatFunction( ) is a reference to a format
function. The format function is automatically passed a record, and
it should return an object with data and
label properties.
#include "DataGlue.as"
// Define the format function. The function should expect a record object.
function formatter (record) {
// Create the object to which the label and data properties are added.
var obj = new Object( );
// Define the label property. This example displays the NAME column of each record
// in uppercase, demonstrating the flexibility of the format function technique.
obj.label = record.NAME.toUpperCase( ) + " (" + record.ID + ")";
// Define the data property. This example assigns the value of the record itself to
// the data property. This is useful in many cases.
obj.data = record;
// Return the object with label and data properties defined.
return obj;
}
// Populate a combo box with the values from a recordset (rs).
DataGlue.bindFormatFunction(myComboBox, rs, formatter);
|