Ask Reuben

Autocompletion

When I type into a Google search box it offers me a list of values based on what I have typed, how can I implement something similar in Genero?

When entering an address field, how can I offer a list of valid addresses? 

When entering a field, how can I offer a list of valid values based on what the user has typed?

Type a phrase into a Google search field and you will see a list of potential search phrases from which you can select a phrase and thus save yourself the effort of typing.  This is known as autocompletion.  

As well as the Google search field which is probably the most well known example, you may also have seen the same design pattern in other data entry fields in other applications.  A common example is address fields, you start typing the address, and the program offers you a list of valid addresses that match what you have typed.

The question I get asked is howto implement a similar design pattern in Genero?

To implement this in Genero requires two things.

First you need to tell Genero that a particular field has some completer logic.  You do this with an EDIT or BUTTONEDIT by adding the attribute COMPLETER.

EDIT f01 = formonly.completer_field, SCROLL, PLACEHOLDER="Enter the field", COMPLETER;

Secondly you need to populate the list that will be offered to the user as they type.  This is done in the ON CHANGE trigger for the selected field and requires your code to use the ui.Dialog.setCompleterItems method to populate a list.  This method takes as argument a DYNAMIC ARRAY OF STRING.  In the ON CHANGE block you have code that populates a variable that has type DYNAMIC ARRAY OF STRING, and then pass this variable to ui.Dialog.setCompleterItems.

In doing so you need to be aware of a few things

  • The number of items in the list cannot exceed 50 items, so you need to make sure that any FOREACH, FOR, WHILE  loop is terminated once the list reaches 50 items in size or else you will have a run-time error.  You probably want to limit to 10 or 20 items in any case.
  • The ON CHANGE block will not be executed straight away.  There is a small delay to see if you are entering multiple key-strokes. The logic will wait until you have stopped typing.  That is if you type “abc” quickly, it won’t populate a list based on “a”, and then “ab”, and then “abc”, it will just populate a list based on “abc”.
  • There may be limited value in offering the list after the user has only typed one or two characters.  I suggest only proceeding with the logic to populate an array and call ui.Dialog.setCompleterItems  if a certain number of characters have been entered.
  • This code is blocking to the UI, it is upto you to ensure that your logic is executed quickly to populate the list.  You do not want this code taking more a second.

So your code may look like …


DEFINE list DYNAMIC ARRAY OF STRING  # List of items that will be used to populate completion list 
...
ON CHANGE completer_field
    -- Empty the list
    CALL list.clear()  
    LET idx = 0
    
    -- Only do this if more than 2 characters entered
    IF completer_field.getLength() > 2 THEN  
        -- Open database cursor based on what has been typed
        -- SQL will typically have a MATCHES e.g. SELECT name FROM names WHERE name MATCHES ?
        LET matches_clause = completer_field , "*"
        OPEN populate_curs USING matches_clause  
        WHILE TRUE
            FETCH populate_curs INTO list_value
            -- Exit loop if no more items
            IF status = NOTFOUND THEN
                EXIT WHILE
            END IF
            LET list[idx:=idx+1] = list_value
            -- Exit loop once 20 items found
            IF idx >= 20 THEN   # Stop once 20 items in list
                EXIT WHILE
            END IF
        END WHILE
        -- Pass list to the dialog
        CALL DIALOG.setCompleterItems(list)  
    END IF 

Refer to the documentation for more details

I do have an example at GitHub in the ex_autocomplete repository

This has a simple example to input country.  Note as I have typed, the list of countries in the list get smaller to match what I have typed.

In this second series of screenshots from a Proof of Concept you will notice I am entering an address.  You don’t have a database table populated with each postal address in the country or world so how is that working?  The answer is that you will find in most countries there are Web Services available that will offer a list of addresses based on a partial match.  These Web Services are quite fast and can normally be relied up to return a value in much less than a second.  The TABLE on the right shows the search phrase, how long the web service call took, and how many responses were received.

By using such an API, the user can type an address much quickly and more importantly more accurately.

Using autocompletion, you not only improve the speed of data input but also improve the quality of data input by helping the user enter a valid formatted value.  If you are not using already in your application, chances are there are places where your application would benefit by adding autocompletion.