The SUBDIALOG clause
Purpose of SUBDIALOG
The SUBDIALOG
clause defines a declarative dialog to be attached to the
current procedural DIALOG
block.
By using form inclusion (with the FORM
clause in LAYOUT
sections) and declarative dialogs + SUBDIALOG
, you enforce code reusability in your
application sources.
Defining the declarative dialog
The declarative dialog is implemented outside the scope of the using DIALOG
block, at the same level as a function.
The declarative dialog can be defined in a different module, to be reused in other
DIALOG
instructions. The sub-dialog module must be imported with the IMPORT FGL
instruction.
Like other module elements such as functions and reports, the name specification is mandatory
when defining a declarative dialog. The name of the declarative dialog will be referenced in a
SUBDIALOG
clause of a procedural dialog instruction.
PUBLIC TYPE t_comment RECORD
c_text VARCHAR(200),
c_checked BOOLEAN
END RECORD
DIALOG comment_input(rc t_comment INOUT)
...
END DIALOG
IMPORT FGL comment
...
FUNCTION mydialog()
DEFINE r_comment comment.t_comment
DIALOG ...
...
SUBDIALOG comment.comment_input(r_comment)
...
END DIALOG
END FUNCTION
See also Identifying sub-dialogs in DIALOG.
Sub-dialogs in form definitions
Implementing a sub-dialog as a declarative dialog in a separate module is typically used in
conjunction with the FORM clause, in the
LAYOUT
section of form specification files:
LAYOUT
...
FORM "comment"
...
END
Semantics with SUBDIALOG
In terms of semantics, behavior and control block execution, a declarative dialog attached to a
procedural dialog with SUBDIALOG
, behaves like a sub-dialog that is defined inside
the procedural DIALOG
block.
For example, BEFORE INPUT
inside an INPUT
block of a declarative dialog will be executed when the focus goes
to one of the fields of that sub-dialog.
Scope of dialog instructions
Other sub-dialogs can reference the attached declarative dialog in the current scope.
NEXT
FIELD
instruction referencing a field in another
sub-dialog:DIALOG ... -- Parent dialog block
...
NEXT FIELD the_comment -- Field of the declarative dialog.
...
END DIALOG
Scope of DIALOG keyword
DIALOG
keyword inside a declarative dialog block to use
ui.Dialog
class methods, it references the current procedural dialog
object:DIALOG comment_input()
...
CALL DIALOG.setFieldActive("the_comment",TRUE)
...
END DIALOG
Writing generic code
To be reused by different procedural DIALOG
instructions, the code of
sub-dialog modules must be generic. However, if the sub-dialog code needs to interact with
the parent DIALOG
, it must be possible to call a function from the parent
DIALOG
.
You achieve this by using function references. Parent modules can then configure the sub-dialog module at runtime, with callback functions:
- Create a user-defined
TYPE
with theFUNCTION
type matching the callback function of the using module:PUBLIC TYPE t_event_callback FUNCTION (event SMALLINT)
- Define a private module variable, with the declared function type. If you want to keep it
private to the module, define a setter function to assign the variable with the callback function
reference:
PRIVATE DEFINE _event_callback t_event_callback
- Define public constants to identify the type of event to be signaled to the parent
dialog:
PUBLIC CONSTANT c_comment_changed = 101 PUBLIC CONSTANT c_comment_checked = 102
- Implement the function to notify the parent
dialog:
PRIVATE FUNCTION _signal_parent(ne SMALLINT) RETURNS () IF _event_callback IS NOT NULL THEN CALL _event_callback(ne) END IF END FUNCTION
- Define the sub-dialog with the callback function reference
parameter:
DIALOG comment_input( cr t_comment INOUT, can_clear STRING, event_callback t_event_callback )
- In the sub0dialog block triggers, call the function to signal events to the parent
dialog:
ON CHANGE is_checked CALL _signal_parent(c_comment_checked)
- In the parent dialog block, define the callback function to be bound to the
sub-dialog:
FUNCTION event_callback(event SMALLINT) CASE event WHEN comment.c_comment_checked LET msg = "Comment checked..." ... END CASE END FUNCTION
- Provide the reference to the callback function as parameter of the sub-dialog, in the
SUBDIALOG
instruction of the parentDIALOG
:SUBDIALOG comment_input(cust_comment, TRUE, (FUNCTION event_callback))
There is no need to implement a lot of complex callback functions: The main purpose is to
indicate to the parent DIALOG
, that something happened in the sub-dialog. The
parent DIALOG
can then query the sub-dialog module for more information, as long as
the sub-dialog module provides functions to query its status.
For a complete example, see Example 3: DIALOG with SUBDIALOG.