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
.
Use this method with care. Let the dialog handle normal navigation automatically,
and jump to a specific row only in the context of an ON ACTION
block.
The 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