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.

Note: Declarative dialog blocks can also be used to implement parallel dialogs.

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.

In the "comment.4gl" module:

DIALOG comment_input()
   ...
END DIALOG
In the using module (note that we use the module prefix here):
IMPORT FGL comment
...
FUNCTION mydialog()
   DIALOG ...
      ...
      SUBDIALOG comment.comment_input
      ...
   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.

For example, to execute a 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

When using the 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:

  1. Create a user-defined TYPE with the FUNCTION type matching the callback function of the using module.
  2. Define a 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.
  3. When the parent DIALOG needs to be notified by some change in the sub-dialog, check that the callback variable is not NULL, and call the function with appropriate values.
Tip: You do not have 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.
PUBLIC TYPE cb_comment_event FUNCTION (event STRING)
PRIVATE DEFINE cb_ce cb_comment_event
...
PUBLIC FUNCTION set_event_callback(f cb_comment_event)
    LET cb_ce = f
END FUNCTION

DIALOG comment_input()
    ...
    IF cb_ce IS NOT NULL THEN
       CALL cb_ce("comment_changed")
    END IF
    ...
END DIALOG

For a complete example, see Example 3: DIALOG with SUBDIALOG.