DekGenius.com
[ Team LiB ] Previous Section Next Section

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);
    [ Team LiB ] Previous Section Next Section