Filling a COMBOBOX item list

The item list of COMBOBOX fields can be initialized at runtime.

Introduction to COMBOBOX fields

COMBOBOX fields are typically used when a field can hold a short predefined list of values. COMBOBOX fields are usually rendered with a drop-down list, from where the end user can choose a value.

Note: All items of a COMBOBOX list will be transmitted to the front-end. Therefore, the number of items that can be selected in a COMBOBOX fields should be limited to 20 to 50 items. If the selection list holds more items, consider using a BUTTONEDIT field, which opens a new window with a TABLE container.
COMBOBOX item lists can be defined in three different ways:
  1. In the form definition file, as a static list of items with single values.
  2. In the form definition file, as a static list of items with value/label pairs.
  3. At runtime when the form is loaded, as single values or value/label pairs.

In this topic we will learn how to implement a COMBOBOX field that is filled dynamically.

For static item list definitions, see COMBOBOX item type.

Defining the COMBOBOX initialization function

In order to fill a COMBOBOX field when the form file is loaded, use the INITIALIZER attribute to define the name of the function that will be called to fill the item list:

COMBOBOX f1 = FORMONLY.city, INITIALIZER=fill_city;

The initialization function name is case-insensitive.

Important: When the form is displayed, make sure that the initialization function is available (the .42m module where the function is defined is loaded).

Defining a global COMBOBOX initialization function

If needed, it is possible to define a common function that implements the item list initialization for all comboboxes of the forms loaded by a program, by using the ui.Combobox.setDefaultInitializer() method.
Tip: Use the TAG attribute to distinguish COMBOBOX fields in all your forms.

Implementing the item list initialization function

The function defined with the INITIALIZER attribute takes a ui.ComboBox object as parameter.

To add items to the selection list of the COMBOBOX field, use the addItem() method of ui.ComboBox:

FUNCTION fill_city(cmb)
    DEFINE cmb ui.ComboBox
    CALL cmb.addItem(101,"Berlin")
    CALL cmb.addItem(102,"Madrid")
    CALL cmb.addItem(103,"London")
    CALL cmb.addItem(104,"Paris")
    CALL cmb.addItem(105,"Rome")
END FUNCTION
Note: If you want to define a list of items with single values, specify only the first parameter of addItem().

Detecting COMBOBOX value change

In order to detect a value change in a COMBOBOX, define the ON CHANGE dialog control block. The ON CHANGE block will be immediately executed when the user selects a new item in the list. One can typically clear other fields related to the COMBOBOX field:

   ON CHANGE city
      LET rec.address = NULL

NULL values in COMBOBOX fields

Pay attention to NULL value handling with COMBOBOX fields:
  • By default, if the field allows nulls, the item list automatically gets a NULL item.
  • It is recommend to disallow nulls with the NOT NULL attribute, and add a special item such as (0,"<Undefined>") to identify a non-specified-value.

Example

The next example shows how to implement the function to fill the item list of a COMBOBOX field with a list of cities. When the COMBOBOX field is changed, the ON CHANGE block is fired and the address field is cleared:

Form file (combobox.per):
LAYOUT
GRID
{
City   : [f1                      ]
Address: [f2                                              ]
}
END
END
ATTRIBUTES
COMBOBOX f1 = FORMONLY.city, INITIALIZER=fill_city;
EDIT f2 = FORMONLY.address;
END
Program file (combobox.4gl):
MAIN
    DEFINE rec RECORD
               city INTEGER,
               address VARCHAR(100)
           END RECORD

    OPEN FORM f1 FROM "combobox"
    DISPLAY FORM f1

    INPUT BY NAME rec.* ATTRIBUTES(UNBUFFERED)
        ON CHANGE city
           LET rec.address = NULL
    END INPUT

END MAIN

FUNCTION fill_city(cmb)
    DEFINE cmb ui.ComboBox
    CALL cmb.addItem(101,"Berlin")
    CALL cmb.addItem(102,"Madrid")
    CALL cmb.addItem(103,"London")
    CALL cmb.addItem(104,"Paris")
    CALL cmb.addItem(105,"Rome")
END FUNCTION