Handling the current row
Query and control the current row in a read-only or editable list of records.
Get the current row
To query the current row of a list, use either the ui.Dialog.getCurrentRow()
method
or the arr_curr()
built-in
function, depending on the context.
The getCurrentRow()
method can be used for a DISPLAY
ARRAY
or INPUT ARRAY
dialog. The method takes the name of the screen array
as the argument to identify the list.
DIALOG
block with two DISPLAY
ARRAY
subdialogs, you can query the current row of a list in the code block of the other
list
controller:DIALOG ...
DISPLAY ARRAY arr1 TO sa1.*
ON ACTION check
IF arr2[DIALOG.getCurrentRow("sa2")].value > 0 THEN
...
END IF
END DISPLAY
DISPLAY ARRAY arr2 TO sa2.*
END DISPLAY
END DIALOG
The arr_curr()
function must be used in the context of the current
DISPLAY ARRAY
or INPUT ARRAY
dialog, or just after executing such
a dialog.
DISPLAY ARRAY
dialog,
the current row and the current screen line can be queried respectively with the
arr_curr()
and scr_line()
functions:DISPLAY ARRAY arr TO sa.*
ON UPDATE
INPUT arr[arr_curr()].* WITHOUT DEFAULTS FROM sa[scr_line()].* ;
END DISPLAY
After the dialog execution, arr_curr()
returns the current row index for the
last executed dialog, until a new list dialog is started.
The row index returned by the arr_curr()
function is constant in the context of
a dialog block, even when removing rows from the array by program. A typical mistake is to reuse the
arr_curr()
index to get data from the new current row, after deleting the last row
of the array.
arr_curr()
without checking for the new
number of rows will automatically create a new program array element when accessing the element in
the MESSAGE
instruction:ON ACTION dialog_delete_row
CALL DIALOG.deleteRow("sr",arr_curr())
MESSAGE "Current item:", arr[arr_curr()].name
The above code works until you reach the last row: When last row is deleted, the
MESSAGE
instruction is automatically creating a new array element at the same index
returned by arr_curr()
.
arr_curr()
, the DIALOG.getCurrentRow()
method is
synchronized with the actual number of rows in the array, as long as methods like DIALOG.deleteRow()
are
used:ON ACTION dialog_delete_row
CALL DIALOG.deleteRow("sr",DIALOG.getCurrentRow("sr"))
MESSAGE "Current item:", arr[DIALOG.getCurrentRow("sr")].name
ON ACTION dialog_delete_row
LET x = DIALOG.getCurrentRow("sr")
CALL DIALOG.deleteRow("sr",x)
LET x = DIALOG.getCurrentRow("sr")
IF x > 0 THEN
MESSAGE "Current item:", arr[x].name
ELSE
MESSAGE "No more rows in the list"
END IF
Set the current row
DISPLAY ARRAY
or
INPUT ARRAY
, use the ui.Dialog.setCurrentRow()
method. This method takes the name of the screen
array and the new row index as
parameters:DISPLAY ARRAY p_items TO sa.*
...
ON ACTION next_empty
LET row = findEmptyRow(p_items)
CALL DIALOG.setCurrentRow("sa", row)
...
END DISPLAY
DIALOG.setCurrentRow()
method will not execute control
blocks such as BEFORE ROW
and AFTER ROW
, and will
not set the focus. If you want to set the focus to the list, you must use the
NEXT FIELD
instruction. This works with DISPLAY
ARRAY
as well as INPUT ARRAY
.ON ACTION
block.fgl_set_arr_curr()
function can also be used. This function must be called
in the context of the current list having the focus.fgl_set_arr_curr()
triggers control blocks such as BEFORE ROW
, while
DIALOG.setCurrentRow()
does not trigger any control blocks.In a DISPLAY ARRAY
using paged
mode with COUNT=-1
, before calling DIALOG.setCurrentRow(
screen-array, row-index )
, call DIALOG.setArrayLength(
screen-array, count )
where count >=
row-index. Otherwise, the setCurrentRow()
call will have no effect, if
the dialog has not yet seen row-index rows through ON FILL
BUFFER
.
Converting visual index to/from program array index
When the end user sorts rows in a table, the program array index
(arr_curr()
) may differ from the visual row index (the row position
as seen by the user).
The ui.Dialog
class provides methods to convert between these
contexts:
BEFORE ROW
trigger and ON
SORT
trigger:FUNCTION disp_row(d,n)
DEFINE d ui.DIALOG, n STRING
MESSAGE SFMT("Row: %1/%2",
d.arrayToVisualIndex(n,d.getCurrentRow(n)),
d.getArrayLength(n))
END FUNCTION
...
DISPLAY ARRAY arr TO sr.*
...
BEFORE ROW
CALL disp_row(DIALOG,"sr")
ON SORT
CALL disp_row(DIALOG,"sr")
...
END DISPLAY
DIALOG.setCurrentRow()
after converting to the program array
index:DEFINE i INTEGER
...
DISPLAY ARRAY arr TO sr.*
...
ON ACTION move_to
PROMPT "Enter row index:" FOR i
CALL DIALOG.setCurrentRow( "sr", DIALOG.visualToArrayIndex("sr", i))
...
END DISPLAY