Input multiple master records + details
---------------------------------------
This directory contains some examples to perform the following task:
a master and a detail table should be edited simultaneously.
(a customer record acts as the master record and an orders table contains the details)
It should be possible to have forward/backward actions to advance to the next physical record for the master in the database and update the details display/input as well.
This is something pretty new in 4GL, this was not possible before.
Particularly, the INPUT of the master by staying visually 'in the dialog' was only possible before by using an INPUT ARRAY on a single record (which is still a good idea as shown later on).
3 DIALOG samples try to achieve this: CustOrders.4gl, CustOrders2.4gl, and CustOrders3.4gl
CustOrders.4gl and CustOrders2.4gl have the same user interface but show
different methods for vaidation of the record data.
Both use an INPUT for the master data and a DISPLAY ARRAY for the details.
CustOrders3.4gl has a more simple user interface (no confirm for the row and no save button) and shows how an INPUT ARRAY on a single row could be used to achieve basically the same result as in CustOrders.4gl and CustOrders2.4gl (with other limitations however).
OrderInput.4gl shows the INPUT of a single master record + details in an INPUT ARRAY (FUNCTION ord_input) and is common to all CustOrders*.4gl samples.
In the AFTER DIALOG of ord_input there is only a small DISPLAY "save data", which is of course a bigger piece of code to write a complete order to the DB.
A real database demo with a similar DIALOG is shown in $FGLDIR/demo/MultipleDialogs/StoresMD/d4_orders.4gl (FUNCTION order_modify)
A central problem in this demo is validation:
When the current customer record is modified, clicking on the previous/next/append buttons should cause the validation of the current record. That means the built-in constraints for the fields must be run thru, as well as the AFTER FIELD of the current field, and the code that is normally in AFTER INPUT to perform checks that cannot be done in AFTER FIELD (due to multiple field dependencies).
In the first 2 samples code is written to achieve that, in the 3rd the INPUT ARRAY with it's built-in triggers does a lot of the work.
CustOrders.4gl
--------------
Implements all customer record validation by 'staying in the dialog' and performs explicit field validation for the user programmed actions.
Each action that require a validation, like going to the next customer or invoking a search, must validate the current INPUT.
Further, those actions must perform the same checking as the built-in 'accept' action of a traditional INFORMIX INPUT instruction:
v1:verify if the field constraints are met (achieved by calling the new DIALOG.validate() method).
v2:call the code that is called in the AFTER FIELD trigger of the field you are currently in.
v3:call the code that is called in the AFTER INPUT trigger.
This is achieved by calling the cust_check_changed() function, which checks the validity in cust_save() by calling cust_check_fields()(calling cust_check_data(), then performing DIALOG.validate() + checking all user programmed field constraints)
The user programmed field constraints are the same in each sample:
1. The customer's address is checked when entered
2. A city cannot be entered without entering a zip code
Advantages: 1. you never have to leave the DIALOG instruction (in comparison to sample2)
Disadvantages:1. need to perform self made (explicite) validation for each of the standard actions
2. a lot of boilerplate code needed to achieve the standard
first/next/previous/last/append/delete actions (in comparison to sample3)
3. the WITHOUT DEFAULTS flag for the INPUT is not usable (see in ../ListAndEditableDetail/README what this means)
CustOrders2.4gl
---------------
- implents all customer record validations by using implicit validation: calling ACCEPT DIALOG
That means that each action which requires validation calls ACCEPT DIALOG.
This lets the DIALOG run thru all 3 validation stages and causes a falling out of the current DIALOG instruction if the validation was succesful.
That means also that one has to maintain a state variable to reenter the DIALOG in a WHILE loop around the DIALOG (in addition to maintain a variable to distinguish between new record or record modification).
The main advantage using that technology is that all you AFTER FIELD constraints can be left in 1 place, it's not needed to use a function for a simple constraint and not needed to duplicate the call in your private validating function compared to sample 1 (see for example the AFTER FIELD cust_name checking) .
Advantages: 1. you only need to check the field constraints at the usual places:
AFTER FIELD and AFTER INPUT and not in each action
2. the WITHOUT DEFAULTS flag for the INPUT is still working like intended (see in ../ListAndEditableDetail/README what this means)
Disadvantages: 1. need to write a WHILE loop with a state variable
2. a lot of boilerplate code needed to achieve the standard
first/next/previous/last/append/delete actions (in comparison to sample3)
CustOrders3.4gl
---------------
-uses an INPUT ARRAY in contradiction to the previous samples where an INPUT was used for the master record
-shows that the standard next/previous/append/delete actions are already builtin into INPUT ARRAY and usable nearly like intended
-implements an MS Access behavior: going to the next/prevoius/first/last row saves the current record to the database without confirmation. If one wants to throw away the changes in the current record, he must press 'Undo'
-shows how the firstrow/prevrow/nextrow/lastrow/append/delete actions can be put into the toolbar and work depending on the context .
That means: if the focus is in INPUT ARRAY-> toolbar buttons act on the INPUT ARRAY
if the focus is in the DISPLAY ARRAY-> toolbar buttons act on the DISPLAY ARRAY
This is similar to how the toolbar is working in MS Access.
(Please note that in earlier versions the single row INPUT ARRAY had only prevrow/nextrow actions)
A further goodie is that INPUT ARRAY/DISPLAY ARRAY now manage the activation of firstrow/prevrow/nextrow/lastrow automatically: no need to call setActionActive by yourself.
Advantages: 1. *a lot* shorter code than in the 2 previous samples because the
next/previous/append/delete mechanisms are already foreseen in INPUT ARRAY
2. you only need to check the field constraints at the usual places:
AFTER FIELD and AFTER ROW (which comparable to the AFTER INPUT trigger of the single record INPUT) and not in each action
Disadvantages: 1. Pressing 'Tab' at the last customer record field moves to the next customer record instead of jumoing to the DISPLAY ARRAY
2. you need to operate on an array which may be inadequate for a large number of database items
CustOrders3.4gl sounds promising but at the moment it's impossible to implement confirmation for the new record (which is not absolutely necessary like MS Access shows).
It's still the usual INPUT ARRAY to input an array and not much foreseen to be synchronized with the data base. However it's intended to be improved in one of the next releases. Then it very likely includes built-in undo support as well as built-in support for synchronizing a row with the database.
The navigation is probably also not what the end user expects, pressing the 'Down' arrow moves to the next record.
Pressing 'Tab' at the end of the record advances also to the next record (which is fine if the INPUT ARRAY runs in a table but not expected for the single record case).
This could be enhanced by giving the INPUT ARRAY a hint that it should make the navigation different in the single record case.
Conclusion:
----------
The first 2 samples show that it's at least possible to achieve the wanted behavior however with a pretty large overhead for implementing the standard actions.
In both cases you need to be careful about the validations for the standard actions and need to add extra code to achieve this.
Both samples lack easy readability because of all the necessary validation stuff which would be an easy game using an INPUT ARRAY.
Sample 3 shows that you can have much less code using INPUT ARRAY, but you still need to know well the pitfalls of how to synchronize the INPUT ARRAY with the database and you will have to live with the limitations (navigation a bit different from expectation)
If this kind of dialog is not a top priority for you, you better wait for an enhanced INPUT ARRAY which has built-in support to sync with the database and enhanced navigation for the single record case to make programming this a joy.