User interface programming / Input fields |
Autocompletion allows to display a list of proposals while the user is typing text into a field.
Text input fields (like EDIT and BUTTONEDIT) can be defined with autocompletion feature, by combining the COMPLETER form field attribute with program code providing the list of proposals in a dynamic array of strings, with the DIALOG.setCompleterItems() method, when the ON CHANGE trigger is fired for the autocompletion field.
In order to enable autocompletion in a text form field, you must define the COMPLETER attribute:
EDIT f1 = FORMONLY.firstname, COMPLETER;
The COMPLETER attribute can be used for EDIT and BUTTONEDIT fields.
The DIALOG.setCompleterItems() method must be used to provide the list of proposal during dialog execution:
DEFINE items DYNAMIC ARRAY OF STRING -- fill the array with items LET items[1] = "Ann" LET items[2] = "Anna" LET items[3] = "Annabel" CALL DIALOG.setCompleterItems(items)
The setCompleterItems() method will raise error -8114 if the list of items contains more than 50 elements. The purpose of autocompletion is to provide a short list of proposals to the user. Note that this error is not trappable with exception handlers like TRY/CATCH, the code must avoid to reach the limit.
When implementing autocompletion, you must detect when the user modifies the field value, to adapt the list of items with the setCompleterItems() method.
INPUT BY NAME rec.firstname ... ON CHANGE firstname CALL fill_proposals_firstname(DIALOG, rec.firstname)
For text fields defined with the COMPLETER attribute, the ON CHANGE trigger will be fired without leaving the field, each time the user types characters in. The event is fired after a short delay, to not overload the UI exchanges between the front-end and the runtime system.
The example below implements form field with autocompletion: Each time the ON CHANGE trigger is fired, the set of proposals is adapted to the current field value, to match names that start with the same characters typed by the user.
LAYOUT GRID { [f1 ] [f2 ] } END END ATTRIBUTES EDIT f1 = FORMONLY.field1, COMPLETER; EDIT f2 = FORMONLY.field2; END
DEFINE all_names DYNAMIC ARRAY OF STRING MAIN DEFINE rec RECORD field1 STRING, field2 STRING END RECORD CALL fill_names() OPEN FORM f FROM "compl" DISPLAY FORM f OPTIONS INPUT WRAP INPUT BY NAME rec.* ATTRIBUTES(UNBUFFERED) ON CHANGE field1 CALL fill_proposals(DIALOG, rec.field1) END INPUT END MAIN FUNCTION fill_names() DEFINE i INTEGER LET i=0 LET all_names[i:=i+1] = "Amanda" LET all_names[i:=i+1] = "Ann" LET all_names[i:=i+1] = "Anna" LET all_names[i:=i+1] = "Annabelle" LET all_names[i:=i+1] = "Barbara" LET all_names[i:=i+1] = "Barry" LET all_names[i:=i+1] = "Brice" END FUNCTION FUNCTION fill_proposals(dlg, curr_val) DEFINE dlg ui.Dialog, curr_val STRING DEFINE curr_set DYNAMIC ARRAY OF STRING, i, x INTEGER LET x=0 FOR i=1 TO all_names.getLength() IF upshift(all_names[i]) MATCHES upshift(curr_val)||"*" THEN LET curr_set[x:=x+1] = all_names[i] END IF END FOR CALL dlg.setCompleterItems(curr_set) END FUNCTION