Ask Reuben

INPUT ARRAY Temporary Row

What is a temporary row?

When is a temporary row created? 

When is a temporary row removed?

How can I tell the runtime not to create a temporary row?

How can I tell the runtime to keep a temporary row?

The INPUT ARRAY instruction has some interesting behaviour that it does silently.  This includes the concept of a temporary row that is created when needed and whether that temporary row should be kept or not.  For the most part it does this well but there are occasionally situations where you have to give a hint that you want to keep or not keep the temporary row.

To understand the concept of temporary row consider these scenarios …

  • The user is in an INPUT ARRAY and intends to enter 10 rows.  For some reason they go beyond the 10 rows, perhaps they press TAB or DOWN one too many times, easy to do, and they end up in row 11.  Realising their mistake they press UP key to move focus back to the 10th row.  What should happen to this 11th row?  Should the array have length 10 or 11?
  • What if from the 11th row instead of pressing UP, the user pressed ENTER (accepted the dialog)?  That is they intended to enter 10 rows but the cursor is sitting on an empty 11th row when they pressed ENTER.  Should this empty 11th row the user has not otherwise done anything too be validated and potentially end up in the database?
  • What if the user deleted the last row of an array, where should the cursor go?  What if the user pressed ENTER at this point?
  • What if the array is a new array and is empty, where should the cursor go? Should the user have to explicitly click append at this point?  What if the user pressed ENTER at this point?

First up there is the concept of AUTO APPEND.  This says to automatically append a new temporary row when one of the following occurs …

  • The user tries to move below the last row, with a DOWN keystroke or with the mouse.
  • The user presses the TAB key when in the last field of the last row.
  • The last row of the list is deleted by the user.
  • The list has the focus and the last row of the list is deleted by program with DIALOG.deleteRow() or DIALOG.deleteAllRows().
  • When the INPUT ARRAY is in a DIALOG block, the list has no rows and gets the focus (A new temporary row is created to let the user enter data immediately)

This behaviour can be denied by setting AUTO APPEND=FALSE as part of the INPUT ARRAY attributes.  If you have an INPUT ARRAY with a fixed number of rows you will typically set APPEND ROW=FALSE, INSERT ROW=FALSE, DELETE ROW=FALSE, AUTO APPEND =FALSE so that the number or rows is fixed.  If MAXCOUNT is set, this will also stop the creation of the temporary row if the row limit has been reached.

If a temporary row has been created, it will be automatically removed if none of the fields has been “touched” when moving up in the list, or if the user leaves the INPUT ARRAY.  A row is “touched” when a user enters data in a field, or when a program simulates user input with a DISPLAY TO, or by setting the DIALOG.setFieldTouched method.

There are two scenarios where you may need to explicitly use the DIALOG.setFieldTouched() method.

With a buffered dialog you may have code like this to populate a field with a complex default value …

BEFORE INSERT
    LET arr[arr_curr()].fieldname = default_fieldname_value()
    DISPLAY arr[arr_curr()].fieldname TO scr[scr_line()].fieldname

… the INPUT ARRAY thinks the program has simulated user input with a DISPLAY and so this temporary row will not be removed.

The solution is to mark the field as not touched so that the temporary row will be deleted.

BEFORE INSERT
    LET arr[arr_curr()].fieldname = default_fieldname_value()
    DISPLAY arr[arr_curr()].fieldname TO scr[scr_line()].fieldname
    CALL DIALOG.setFieldTouched("fieldname", FALSE)

The second scenario occurs with UNBUFFERED dialogs where the explicit DISPLAY TO statement is no longer required.    You may have a BUTTONEDIT where the BUTTONEDIT action is used to populate a value (zoom / lookup windows)…

ON ACTION zoom INFIELD fieldname
    LET arr[arr_curr()].fieldname = zoom()

… in this scenario the INPUT ARRAY will think that the program has not simulated any input as there is no DISPLAY TO statement and the criteria is met to remove the temporary row.  The solution in this case is to mark the field as touched so that the row is not removed.

ON ACTION zoom INFIELD fieldname
    LET arr[arr_curr()].fieldname = zoom()
    CALL DIALOG.setFieldTouched("fieldname", TRUE)

The above scenario is typically encountered when there is a small number of fields with good defaults and only one field requires selection of a value from a BUTTONEDIT.  In most circumstances there is a field somewhere in the row that requires typing that will mark the row as touched but if the only thing the user needs to do with a new row is select a value from a BUTTONEDIT this scenario can occur.

These are the two scenarios where you will need to consider adding a DIALOG.setFieldTouched call, otherwise the runtime silently does what you expect it to.

You can read more about automatic temporary row creation and removal here .  I would encourage you to create a simple little INPUT ARRAY example and experiment noting when the temporary row is create and removed, and the impact of a DIALOG.setFieldTouched call with these scenarios.

If you unsure about what a temporary row looks like, these 3 screenshots may help.

  1. User is on the last row …

2. User presses DOWN, a new row is created and the cursor sits in this row …

3. User presses UP and the new temporary row has been removed …