Recipe 11.4 Making Dependent Menus

11.4.1 Problem

You want to make the items in one menu (list box or combo box) dependent on the user's selection in another form element.

11.4.2 Solution

Create a custom makeDependent( ) method for all combo boxes and list boxes.

11.4.3 Discussion

Making a menu depend on the value of another form element is a common practice. For example, you might want to present a list of minivans instead of sports cars if the customer indicates that safety and seating capacity are his top priorities when choosing a new car.

You can create a dependent menu by following these steps:

  1. Create an array of data providers (i.e., an array of arrays) for the dependent menu. Each data provider element should correspond to an item in the master menu. In other words, the index of each data provider element should match up with the index of an item in the master menu.

  2. Define the setChangeHandler( ) method of the master menu so that it automatically calls a function when the user selects an item from the master menu.

  3. In the callback function, use the getSelectedIndex( ) method to determine the selected index of the master menu. Then set the data provider of the dependent menu to the element from the data providers array of the same index.

This feature set is much easier to implement if you make a custom makeDependent( ) method for FSelectableListClass. This class is the superclass for both list boxes and combo boxes, so our custom method is available to both kinds of menus. The makeDependent( ) method should take two parameters:


This should be a reference to an array of data providers. Each element of the array should match up with one of the items in the master menu.


This is a reference to the master menu.

Here is our custom makeDependent( ) method:

FSelectableListClass.prototype.makeDependent = function (multiDataProvider, master) {
  // Set the master menu's change handler to the updateView(  ) method (see following)
  // for the dependent menu.
  master.setChangeHandler("updateView", this);

  // Set the dependent menu's properties to the values passed in as parameters.
  this.multiDataProvider = multiDataProvider;
  this.master = master;

// updateView(  ) is called whenever the user selects an item from the master menu.
FSelectableListClass.prototype.updateView = function (  ) {

  // Get the index of the selected menu item from the master menu.
  var selectedIndex = this.master.getSelectedIndex(  );

  // Get the data provider that corresponds to the selected index.
  var dp = this.multiDataProvider[selectedIndex];

  // Set the data provider for the dependent menu.

Here is an example of the makeDependent( ) method in use:

// In this example, create two combo boxes. Space them 150 pixels apart.
_root.attachMovie("FComboBoxSymbol", "myComboBox1", 1);
_root.attachMovie("FComboBoxSymbol", "myComboBox2", 2, {_x: 150});

// Create the master menu's data provider array and use it to populate the menu.
items1 = ["a", "b", "c"];

// Create the multiDataProvider array. It has three elements, each corresponding to
// an item in the master menu. Each element is a data provider. In this case, they
// are each simple array data providers.
items2 = new Array(  );
items2.push(["1 a", "2 a", "3 a"]);
items2.push(["1 b", "2 b", "3 b"]);
items2.push(["1 c", "2 c", "3 c"]);

// Call the makeDependent(  ) method from the dependent menu. Pass it the
// multiDataProvider and a reference to the master menu.
myComboBox2.makeDependent(items2, myComboBox1);

It is important to note that the makeDependent( ) method sets the master menu's change handler, which would conflict with another change handler defined for the master menu. In the majority of situations this should not be an issue because it is unlikely that you will need to add any other actions to the master menu's change handler. However, should you decide to do this, make sure to include a call to the master menu's updateView( ) method in the new change handler function. For example:

function newOnChange(masterMenu) {

  // You must include a call to the menu's updateView(  ) method.
  masterMenu.updateView(  );

  // Additional actions go here.


    Part I: Local Recipes
    Part II: Remote Recipes