Folder example
--------------
This example shows how to use a master record and multiple sub dialogs to input details in several folder pages.
To show how complex it was before, there is a Folder_old.4gl example that compiles with older versions and does basically the same as the Folder.4gl sample.
Each sub dialog contains some useful validation code to prove that we are coming thru when jumping from one page to the other.
Folder_old.4gl:
A big while loop was needed with page actions in each page to leave the current interaction statement, set the state, and jump into the next dialog. The difficulty in leaving the dialogs to move to another page is in using the ACCEPT INPUT statement properly (introduced for this purpose). Otherwise, the AFTER FIELD/AFTER ROW/AFTER INPUT triggers are not called (exiting the current dialog with EXIT INPUT will cause this to happen, and you will need to call your validations again for each page action).
You need to set the correct state before each ACCEPT INPUT, also for the 'accept' action, because if a validation in between fails, state still has the value of the last clicked action. In the cancel case, we need to check int_flag.
If you want to add another sub dialog, you must edit all existing dialog statements to add the new action for activating the new sub dialog.
It's annoying that it is not possible for the user to simply click into the master dialog if the focus is in one of the pages.
You cant't tab simply from the master to the details.
When leaving a particular INPUT, you should check if something has been changed for the insert/update case.
It's obvious that this programming style is only a vehicle to make things happen, and the visual results are also not fully satisfying.
Folder.4gl
All those headaches now disappear when you use the DIALOG statement.
Each page can be reached without the need for an action to raise it:
the master record is always reachable with this mode. The AFTER FIELD/(AFTER ROW)/AFTER INPUT triggers of one sub dialog are called when you move to another sub dialog. In the AFTER INPUT trigger you can place database instructions as in the Folder_old sample.
But, just like in the old sample, a sub dialog can be visited multiple times, so it must be checked in case something has to be inserted/updated.
If we want to reset the internal flags that indicate a field of a sub dialog has been changed, we must call the DIALOG.setTouchedFlag() function (of course, there are also other methods to check whether a field has changed: make a record copy or use ON CHANGE).
To indicate that a validation has gone wrong, the NEXT FIELD statement is used (as usual) to interrupt the DIALOG's internal state machine and stay in the current (invalid) sub dialog.
Folder2.4gl
The Folder2 sample shows that it's also possible to fill in all data in the sub dialogs first, and to do the database activity later in the AFTER DIALOG. This lets the database code run at one central place of the multiple dialog in a transaction. It also avoids checking whether a sub dialog has been entered/left twice.
The 'ok' action then starts the transaction, the 'cancel' action cancels everything (with no need to cleanup things done earlier in the dialog).
The Folder2 sample also shows that there is no difference in how the sub dialogs work if they are not placed inside folders, by running the same code again in another form (with no folder at all).
Source code splitting:
------------------------------
In the Folder_old.4gl it was possible to put the code for the individual (sub) dialogs into different source files (not actually done in the sample )
For example:
WHEN "page1"
LET state="invalid"
INPUT ARRAY donations WITHOUT DEFAULTS FROM donations.* ATTRIBUTES(UNBUFFERED)
...
END INPUT
could be coded by using a function call to perform the INPUT ARRAY
WHEN "page1"
LET state="invalid"
CALL input_donations()
and "input_donations" could reside in an extra source code module. This could be done for all other dialogs used in the WHILE loop. This helps to prevent a huge monolithic source code module, regardless of the fact that the modules have a strong affinity in terms of the folder states.
Now, with multiple dialogs and SUBDIALOGs and embeddable FORM's this is done but in a much cleaner way.
Each SUBDIALOG can be moved into an individual module and the form belonging to that source code module can be in a separate form file which is then included via "FORM" in the master form.
In the example this is done for the "donations" sub DIALOG. It resides in a module called "donations.4gl" and the form for that module is in "donations.per".
Extra sugar: donations.4gl contains a MAIN function which can call the individual dialog standalone for testing (just do fglrun donations)
This shows that there is no relation to the master dialog anymore,
it helps much for splitting the work for individual dialogs into separate testable pieces.