Handling INPUT ARRAY temporary row creation

If a list is driven by an INPUT ARRAY sub-dialog, the user can create a new temporary row at the end of the list. The new row is called "temporary" because it will be automatically removed if the user leaves the row without entering data. If data is entered by the user or by program (setting the touched flag), the temporary row becomes permanent.

A temporary row is promoted to a permanent row under certain conditions described in this topic. We distinguish also explicit temporary row creation from automatic temporary row creation.

Temporary row creation is different from adding new rows with the DIALOG.appendRow() method; When appending a row by program, the row is considered permanent and remains in the list even if the user did not enter data in fields.

Conditions to make a temporary row permanent

The temporary row is made permanent, when moving down to the next new temporary row, or if the modification flag of one of the fields is set. The modification flag of a field is typically set when the user enters data in the form field and tabs to another field (or validates the dialog), but this modification flag can also be set by program, with a DISPLAY TO / BY NAME instruction or with the DIALOG.setFieldTouched() method. When the modification is set by program, NOENTRY fields are ignored, however, fields dynamically disabled by DIALOG.setFieldActive() are taken into account.

Explicit temporary row creation

Explicit temporary row creation takes place when the user decided to append a new row explicitly with the append action. If the list is empty, an insert action will have the same effect as an append action (i.e. a temporary row will be created at position 1).

Automatic temporary row creation

By default, to follow the traditional behavior of singular INPUT ARRAY instructions, automatic temporary row creation takes place when:

Avoiding temporary row creation

Temporary row creation is useful because, in most cases, INPUT ARRAY is used to edit existing rows and append new rows at the end of the list. However, you might want to deny row addition or at least avoid the automatic temporary row creation when the last row is deleted or when an empty list gets the focus.

To avoid explicit temporary row creation, prevent INPUT ARRAY to defined the implicit append action by setting the APPEND ROW attribute to FALSE in the ATTRIBUTE clause:
DIALOG ATTRIBUTES(UNBUFFERED)
   INPUT ARRAY p_items FROM sa.* ATTRIBUTES(APPEND ROW=FALSE)
   ...
   END INPUT
END DIALOG
Even if APPEND ROW /INSERT ROW attributes are set to FALSE, automatic temporary row can occur when the user deletes the last row of the list or if the list is empty and gets the focus. This is the traditional behavior, like in singular INPUT ARRAY instructions. Without automatic temporary row creation, a singular INPUT ARRAY instruction would have no rows to edit if the dialog is started with an empty array. However, with multiple dialogs, it is common that an editable list controlled by an INPUT ARRAY sub-dialog can be empty and get the focus (for example, in a master/detail form with order header and order lines, when creating a new order, it has no lines). By default, when the focus goes to an INPUT ARRAY sub-dialog, it will behave as the singular INPUT ARRAY (i.e. create an automatic temporary row if the list is empty). If needed, you can avoid automatic temporary row creation by setting the AUTO APPEND attribute to FALSE:
DIALOG ATTRIBUTES(UNBUFFERED)
   INPUT ARRAY p_items FROM sa.* ATTRIBUTES(AUTO APPEND=FALSE)
   ...
   END INPUT
END DIALOG

To fully deny row addition, set both APPEND ROW and AUTO APPEND to FALSE.

If both APPEND ROW and INSERT ROW attributes are set to FALSE, the dialog will deny explicit temporary row creation but also automatic temporary row creation, as if AUTO APPEND = FALSE would be used.

Row creation control blocks for temporary rows

In order to control row creation, the DIALOG instruction provides the BEFORE INSERT and AFTER INSERT control blocks. The BEFORE INSERT trigger is invoked after a new row was inserted or appended, just before the user gets control to enter data in fields. REgarding temporary rows, the AFTER INSERT block is invoked if data has been entered and you leave the new row (for example, when the focus moves to another row or leaves the current list), or if the dialog is validated with ACCEPT DIALOG. No AFTER INSERT block is invoked if the user did not enter data: The temporary row is automatically deleted.

In the BEFORE INSERT control block, you can tell if a row is a temporary appended one by comparing the current row (DIALOG.getCurrentRow() or ARR_CURR()) with the total number of rows (DIALOG.getArrayLength() or ARR_COUNT()). If the current row index equals the row count, you are in a temporary row.

AFTER ROW and temporary rows

When a temporary row as automatically removed, the AFTER ROW block will be executed for the temporary row, but ui.Dialog.getCurrentRow() / ARR_CURR() will be one row greater than DIALOG.getArrayLength() / ARR_COUNT(). In this case, ignore the AFTER ROW event.