Ask Reuben

Skipping Fields

How do I jump a field? 

How do I make it so that a user cannot click in a field?

Historically Text User Interface (TUI) applications had no method to show that you could not edit a field.  In Informix-4gl if you wanted to prevent a user editing, you might skip over a field with something like …

BEFORE FIELD fieldname
    NEXT FIELD NEXT

… or more likely there would be a function that contained the business logic if the user could edit a field …

BEFORE FIELD fieldname
    IF NOT fieldname_can_edit() THEN
        NEXT FIELD NEXT
    END IF

If you were more prudent and wanted to consider the fact that the developer might be going backwards you might have coded …

BEFORE FIELD fieldname
    IF NOT fieldname_can_edit() THEN
        IF going_backwards() THEN
            NEXT FIELD PREVIOUS
        ELSE
            NEXT FIELD NEXT
        END IF
    END IF

… where your library function going_backwards() used fgl_lastkey() and fgl_keyval() to determine if the user was moving forwards or backwards through the list of fields.

When transforming your sources to Genero and a GUI Graphical User Interface, this code pattern is one you should consider removing and replace with use of the ui.Dialog.setFieldActive(fieldname, boolean) method.  Typically your code then becomes …

BEFORE INPUT
   CALL DIALOG.setFieldActive("fieldname", fieldname_can_edit())

… and there is no code in the BEFORE FIELD to skip over the field.

This method should be preferred because ,,,

  • a graphical user interface will dim this disabled field and make it obvious to the user that they cannot edit this field.  The UI will not respond if the user clicks in this field.
  • the user interface will manage the determination of the next field if the user attempts to enter this field using keyboard navigation (pressing Tab, Shift-Tab).
  • with a function such as going_backwards(), how do you determine if the user is going backwards or forwards as a result of a mouse click?

The one gotcha is that the onus is on you to make sure that setFieldActive() is called whenever a change occurs in one of the parameters that can influence if the field is active or not.  This means that setFieldActive() or the function it is in, may need to be called from one or more of BEFORE INPUT, ON CHANGE, ON ACTION.  I typically take a pessimistic approach and end up with a single function that controls the state of all the fields in my dialog that is called from many places.  Only if that function has some complex logic will I try and optimise how often that function is called.

The screenshot below shows field2 after setFieldActive(“field2”, FALSE) has been called, note how field2 has a different background, no PLACEHOLDER text.  It should be obvious to the user that they cannot click in field2 and edit a value like they can with the other fields …

If you still have in your code base, patterns of BEFORE FIELD fieldname … NEXT FIELD NEXT, you ought to consider transforming your code to use ui.Dialog.setFieldActive().  A coding standard you might consider implementing is that there should be zero instances of NEXT FIELD NEXT and NEXT FIELD PREVIOUS in a GUI application.

As illustrated here, this setFieldActive method is also useful for the case when the value in one field influences if another field is active.