Array binding in list controllers
Program array elements are bound to screen arrays elements in the definition of the
DISPLAY ARRAY
or INPUT ARRAY
list dialog.
Array elements are bound to screen array fields by position
A screen array groups a set of fields to define list container columns in a .per form file.
When using a program array in DISPLAY
ARRAY
or INPUT ARRAY
, the elements of the array are bound by position to
the fields of the associated screen array.
...
INSTRUCTIONS
SCREEN RECORD sa (
FORMONLY.col_pkey,
FORMONLY.col_name,
FORMONLY.col_details
);
END
In the program file (note the name of the record elements can be different from screen array element names):
DEFINE arr DYNAMIC ARRAY OF RECORD
pkey INTEGER,
name VARCHAR(50),
details VARCHAR(50)
END RECORD
...
DISPLAY ARRAY arr TO sa.*
...
END DISPLAY
LAYOUT
section, the order of the columns (field item
tags) does not need to match the order of the fields in the screen array. To get the tabbing
order defined by the form, you will however have to use OPTIONS FIELD ORDER FORM
in the
program.Using PHANTOM fields to get the same columns as the database table
In most cases, the record list data comes from a database table. A program array can be easily defined with the same structure as its corresponding database table, by using a schema file and a DEFINE LIKE instruction:
SCHEMA stores
DEFINE arr_cust DYNAMIC ARRAY OF RECORD LIKE customer.*
PHANTOM
field definition in the form. The screen array will hold all
columns of the table and program array. It is then possible to bind the program array to the screen
array: The number of elements in the program array and in the screen array will
match....
ATTRIBUTES
EDIT c1 = FORMONLY.col_pkey; -- Column in TABLE container
EDIT c1 = FORMONLY.col_name; -- Column in TABLE container
PHANTOM FORMONLY.col_details; -- Not used in LAYOUT (only in screen array)
END
...
Array sub-records can be bound to flat screen arrays
If additional fields are required to hold data that is not stored in the database table, it is possible to define the program array with a sub-record matching the database table structure, and define volatile data fields beside this record.
SCHEMA stores
DEFINE arr DYNAMIC ARRAY OF RECORD
checked CHAR(1),
sql_data RECORD LIKE items.*,
comment STRING
END RECORD
MAIN
...
INPUT ARRAY arr FROM sa.* ...
...
END MAIN
Here the "checked
" and "comment
" members are not part of the
database table, while the "sql_data
" element is defined LIKE
the
"items
" table of the "stores
" schema. All members defined in this
dynamic array can be bound to a flat screen array.
Complete example using additional fields and phantom fields
In the next example, the program array is defined with more elements than the corresponding database table, and the form definition file uses phantom fields, to hide some database columns.
LAYOUT
GRID
{
<TABLE t1 >
[c1 |c2 |c3 ]
[c1 |c2 |c3 ]
[c1 |c2 |c3 ]
[c1 |c2 |c3 ]
< >
}
END
END
ATTRIBUTES
EDIT c1 = FORMONLY.pkey, TITLE="PKey", NOENTRY;
EDIT c2 = FORMONLY.name, TITLE="Name";
CHECKBOX c3 = FORMONLY.checked, TITLE="Checked";
PHANTOM FORMONLY.details; -- Not used in layout
PHANTOM FORMONLY.comment; -- Not used in layout
END
INSTRUCTIONS
SCREEN RECORD sa(
FORMONLY.checked, -- Note order is different to the layout
FORMONLY.pkey,
FORMONLY.name,
FORMONLY.details,
FORMONLY.comment
);
END
TYPE t_type RECORD
checked CHAR(1),
sql_data RECORD -- Could be RECORD LIKE items.*
pkey INTEGER,
name VARCHAR(50),
details VARCHAR(200)
END RECORD,
comment STRING
END RECORD
DEFINE arr DYNAMIC ARRAY OF t_type
MAIN
OPTIONS INPUT WRAP, FIELD ORDER FORM
CALL create_db()
CALL fill_array()
OPEN FORM f1 FROM "form1"
DISPLAY FORM f1
INPUT ARRAY arr FROM sa.* ATTRIBUTES(WITHOUT DEFAULTS)
BEFORE ROW
MESSAGE arr[arr_curr()].sql_data.details
END INPUT
END MAIN
FUNCTION create_db()
DEFINE rec t_type
CONNECT TO ":memory:+driver='dbmsqt'"
CREATE TABLE items (
pkey INTEGER PRIMARY KEY,
name VARCHAR(50),
details VARCHAR(200)
)
FOR rec.sql_data.pkey=100 TO 150
LET rec.sql_data.name = SFMT("Item %1",rec.sql_data.pkey)
LET rec.sql_data.details = SFMT("Details for %1",rec.sql_data.pkey)
INSERT INTO items VALUES ( rec.sql_data.* )
END FOR
END FUNCTION
FUNCTION fill_array()
DEFINE rec t_type,
x INTEGER
DECLARE c1 CURSOR FOR
SELECT 'N', items.*, '' FROM items ORDER BY pkey
CALL arr.clear()
FOREACH c1 INTO rec.*
LET x = x+1
LET arr[x].* = rec.*
END FOREACH
FREE c1
END FUNCTION