template_banner.gif Main Index  PREV  NEXT

Valid HTML 4.01!   Valid CSS!

Conventions

The Menu-Parent-Child Hierarchy

The following sections may contain various combinations of these objects:

Figure 1 - Component Hierarchy

s02_image001.gif

MENU This is a screen from the standard Menu and Security System. It shows a list of options that are available to the user. Options to which the user has not been granted access will not be displayed.
PARENT This is a form component which has been selected from a menu screen. This may contain a set of Navigation Buttons (a mini menu) which allows other options to be selected. Options to which the user has not been granted access will be dimmed and inoperative.
CHILD This is a form component which has been selected from another form component, not from a Menu screen. A child component may have children of its own.

Communication between Menu and Parent.

The Menu and Security System uses the following code to activate any selection made by the user:-

$$component     = <selection>
$$instance      = ""
$$properties    = ""
$$operation     = "EXEC"
$$params        = ""
call ACTIVATE_PROC

$$component is actually the Transaction ID which is contained with the Menu database. It is usually the same as the component ID, but it can be different. Refer to Menu and Security System, Appendix E: Component Identities for more details.

$$instance is the name to be given to this instance of the component. This is usually left empty as the choice of name is decided by settings on the Menu database. Refer to Menu and Security System, Appendix D: Instance Names for more details.

$$properties is used to define or override certain properties when the instance is first created.

$$operation is set to EXEC so that the component instance is activated at its <EXEC> trigger rather than any custom operation.

$$params is a string that may be passed as an argument on the ACTIVATE command. It is treated as an associative list, therefore it may contain any number of item=value pairs. It is initially empty, but may be filled using data obtained from the Menu database:

Some components may be programmed to accept a single string parameter whereas others may not. For this reason the standard ACTIVATE_PROC uses code similar to the following to activate the instance:-

activate lv_Instance.$$operation()             ; without PARAMS
if ($procerror = <UPROCERR_NPARAMETERS>)       ; param mismatch
   activate lv_Instance.$$operation($$params)  ; try with
endif

This first tries to activate without any parameters, but if this fails it tries a single argument which may or may not be empty. No component which is to be activated directly from a menu should therefore be programmed to accept more than a single string parameter, and should be capable of dealing with an empty string.

Communication between Parent and Child

When running a form component the user may wish to run another form component. Navigation Buttons within the component allow the user to activate another component without having to return to a menu screen. These Navigation Buttons act as a 'mini menu'. In this situation the current component is known as the PARENT and the component to be activated is known as the CHILD.

It is also common practice for the current context to be passed down from the PARENT to the CHILD so that the CHILD form can automatically retrieve the current object without further intervention from the user. To achieve this the <detail> trigger of the Navigation Button should contain code similar to the following:-

$$component    = $fieldname
$$instance     = ""
$$properties   = ""
$$operation    = ""
call LP_PRIMARY_KEY
call ACTIVATE_PROC

You should have noticed that this uses the same ACTIVATE_PROC that was described in the previous section.

The local proc LP_PRIMARY_KEY is used to fill global variable $$PARAMS with the current context. It contains code similar to the following:-

entry LP_PRIMARY_KEY   ; load parameter to pass to child process

$$params = $keyfields(<MAIN>,1)    ; load names of pkey items
setocc "<MAIN>",$curocc(<MAIN>)    ; make occurrence current
putlistitems/id $$params           ; insert representations

end LP_PRIMARY_KEY

The local proc LP_PRIMARY_KEY is included in the code which is inherited from the component template and can deal with a primary key which contains any number of fields. This standard code should not require any additional action by the developer.

In order to deal with the contents of $$PARAMS the <EXEC> trigger of the child component should contain code similar to the following:-

params
   string  $params$    : IN
endparams

getlistitems/id/component $params$     ; copy to component variables

clear/e "<MAIN>"
getlistitems/occ $params$, "<MAIN>"
retrieve/x "<MAIN>"

if (!$dbocc(<MAIN>))
   putmess "primary key: %%$params$"
   message $text(M_90007)  ; no record found
   exit(1)
endif

edit

This code will be automatically inherited from the component template and may contain minor differences between one template and another. This is because each template is purpose built to deal with a particular set of circumstances and may be required to behave in a different manner.

Communication between Child and Parent

If the child makes a modification to the database it is a good idea for the parent to be informed of what has changed so that it can update its display accordingly. This can be done with every STORE that is performed in the child rather than waiting for the child to terminate and return control to its parent. However, the passing of parameters from parent to the <exec> trigger of the child is one way only. If details need to be passed back from the child to the parent there are the following choices:

Use the postmessage/sendmessage command

This is the most common method and has been built into the standard code for various types of form component. For example, when a form of type Add, Update or Delete has successfully modified the database it sends a message (a single string containing an associative list) to its parent which identifies the occurrence and the action taken. This message is received and processed in the <async interrupt> trigger of the parent.

The <STORE> trigger will typically contain code similar to the following:-

$$msgdata = ""     ; load message for parent
putlistitems/occ $$msgdata, "<MAIN>"
$$msgid = "ENTRY_ADDED"

call STORE_PROC

This loads the data from a modified occurrence into $$MSGDATA as an associative list.

The global STORE_PROC contains code similar to the following:-

store
if ($status < 0)
   message "Store failed"
else
   if ($status = 1)
      message "No modifications found - store not executed"
   else
      commit
      if ($$msgdata != "")
         ; post message to parent process
         call POSTMESSAGE($$msgdst,$$msgid,$$msgdata)
         if ($procerror)
            call PROC_ERROR($procerrorcontext)
         endif
      endif
   endif
endif

Provided that the STORE is successful a message will be posted to the parent instance. This should be received and processed in the <async. interrupt> trigger of the parent using code similar to the following:-

if ($msgid = "ENTRY_ADDED")                ; entry added
   creocc "<MAIN>",$curocc(<MAIN>)+1
   getlistitems/occ/init $msgdata, "<MAIN>"
   ; retrieve any inner/up entities
endif

if ($msgid = "ENTRY_UPDATED")              ; entry updated
   creocc "<MAIN>",$curocc(<MAIN>)+1
   getlistitems/occ/init $msgdata, "<MAIN>"
   retrieve/o "<MAIN>"
   if ($status = 0)                        ; does not exist
       discard "<MAIN>"
   else
       getlistitems/occ $msgdata, "<MAIN>"
   endif
endif

if ($msgid = "ENTRY_DELETED")              ; entry deleted
   creocc "<MAIN>",$curocc(<MAIN>)+1
   getlistitems/occ/init $msgdata, "<MAIN>"
   retrieve/o "<MAIN>"
   discard "<MAIN>"
endif

Note that this uses the contents of $MSGDATA (formerly $$MSGDATA) to make any necessary adjustments to the occurrences being displayed. It does not have to perform a CLEAR and RETRIEVE to rebuild the whole display.

It is possible for a child component to perform multiple updates and therefore send multiple messages back to its parent.

Activate a custom operation

If a message other than a single string needs to be passed back to the parent form then custom code similar to the following will be required:-

.....
activate <instancename>.CUSTOM_OPERATION(arg1,arg2,,,,argN)
.....

This will require an equivalent operation in the target component using code similar to the following:-

operation CUSTOM_OPERATION
params
   type  arg1   : IN/INOUT/OUT
   type  arg2   : IN/INOUT/OUT
   ...
   type  argN   : IN/INOUT/OUT
endparams

.....
.....

end CUSTOM_OPERATION

This can be implemented in one of the following ways:-

As with messages it is possible for this child-to-parent communication to take place multiple times before the child is terminated.


copyright.gif http://www.tonymarston.net