Following is a David-Adams-length summary about subforms


A self-quiz:

1) All 4D commands and functions in a subform are executed in the context of 
the subform. Except for a few. What are the exceptions?

2) How can a method check if it is running in a form or subform?

3) When will the On Bound Variable Change event not happen when the Subform 
Container variable changes?

4) When will OBJECT GET SUBFORM not return the form name set by OBJECT SET 

5) Which form events will be triggered by redisplaying a page with a subform?

6) What happens when a subform is resized? How to manage it?

7) Is the timer in SET TIMER associated with the process or the form?

8) When will On Activate not be triggered when a subform becomes active?

9) Besides using process variables (including sets and Named selections), how 
can the subform interact in the parent form context?

If the answers are not apparent from the references below, let me know.


When the information documented below you can answer the questions and predict 
what will happen when working with subforms.

The 4D documents describe (almost) completely all the details regarding the use 
of forms and subforms (widgets). However, this knowledge is scattered through 
many different areas of the 4D Design Reference and 4D Language reference and 
the Knowledgebase. I have tried to list them below. You also should check the 
iNug for almost anything that Keisuke Miyako has written.


Some of the older 4d documents recommend use of SET TIMER in the communication 
between Parent form and subform because of the issues of when the subform and 
objects are instantiated. There are several alternatives.

Some of the recommendations for the use of timers (as opposed to alternatives) 
is related to the use of Open window instead of the recommended Open form 
window. This is discussed by Keisuke Miyako on the iNug: Re: Resizable subforms.

Another old-fashioned way of communicating is POST KEY. No longer needed.


1) One area that I don’t think 4D does a good job of documenting is the issue 
of resizing in subforms. I am confident of the following:
The On Resize event is never triggered in the subform.

When the subform is first displayed, either by being already on the form or 
through OBJECT SET SUBFORM, 4D does not resize the objects on the subform. 
However if the parent form is subsequently resized, 4D will resize the objects 
on the subform according to the Resizing Options properties.

The standard way to handle this issue is either a) never resize the subform, or 
b) somewhere in the loading process (discussed below) the subform uses OBJECT 
GET SUBFORM CONTAINER SIZE to get its own size and resizes itself.

This issue is also discussed in the note below copied from Keisuke Miyako.

2) A second issue not discussed in the 4D documents is the issue of what 
happens to subforms when you leave the page is also missing from official 4D 
documentation but it is discussed below definitively Keisuke Miyako. 

To add to what he is saying on this: if you are on page 2 displaying a subform, 
then go to another page and change the page 2 subform variable, if you return 
to page 2, you get an On Load event in the subform, not an On Bound Variable 
Changed event.

3) A third issue is clarifying that OBJECT SET SUBFORM does not trigger an On 
Load event in the subform: a) if you are on another page, or, b) it is already 
being displayed.


The Subform will NOT get an On Load if it is already being displayed, even if 
OBJECT SET SUBFORM is called again.


The Subform will get an On Bound Variable Change only if the subform container 
variable changes while the subform is already being displayed.


The commands and functions that can be executed in the parent form context from 
a subform are GOTO OBJECT and FORM GOTO PAGE and FORM Get current page. Am I 
missing anything? Of course, process variables, sets, selections, etc, are 
shared with all forms and subforms in a process.


I did not expect this but it’s rational: A click in the subform will trigger an 
On Clicked in the Container Form as well.


Here’s the list of 4D documents, Knowledgebase, and (some) inug messages 
describing subforms (let me know if I’m missing something):

4D Design Reference: Subforms and Widgets: Overview
4D Design Reference: Subforms and Widgets: Page subforms

4D Language Reference: Form Events
Form event
Remember: When the SET TIMER command is executed in the context of a subform 
(form method of the subform), the On Timer event is generated in the subform 
and not at the parent form level.

4D Language Reference : Objects (Forms)

4D Language Reference: Language 

4D Language Reference : Entry Control

4D Widgets
4D Widget components  

4D Design Reference
Subforms and Widgets

4D Design Reference: Working with active objects
Subforms (just 2 sentences)

4D Design Reference: Subforms and Widgets: Page subforms


Tech Tip: Using widgets on page 2+ (2013) <>

Tech Tip: Horizontally resize the SearchPicker object <>

Tech Tip: Using Multiple Widgets on the same form (2012) <>

[4D Summit Europe 2013] Subforms <>
Shows how to tell if running in a subform or form. Would have to be careful 
with nested subforms

If (Is nil pointer(OBJECT Get pointer(Object subform container)))

Tech Tip: Output Subforms and Object Get Subform <>

An excellent note about the timing for OBJECT SET SUBFORM and OBJECT GET 
SUBFORM. Answers the question about when OBJECT GET SUBFORM does not return the 
name of the subform set with OBJECT SET SUBFORM

Tech Tip: How to populate and self-document an Array with a Form Object's 
Default Values <>
The dangers of using process variables in subforms

Tech Note: Sliding Tab in 4D <>
Shows what can be done in 4D with subforms. The reason for using the On Timer 
event is not clear to me.

Tech Tip: Understanding when 4D displays form updates (2015) <>
An excellent note that explains the interaction between OBJECT SET SUBFORM and 
the sequence of execution. In addition to the suggested SET TIMER and CALL 
PROCESS is the option of waiting in the parent form for an event triggered from 
the subform using CALL SUBFORM CONTAINER

“Regardless of how many or how often fields, variables, and widgets are updated 
in value or location, the change is not reflected on a 4D form until the 
execution pointer exits the method being executed. Once the execution pointer 
returns to the 4D runtime, the last values and moves are applied to the form.

Subforms can now be used to create highly sophisticated forms. Subforms can be 
swapped in an out of a parent form, OBJECT SET SUBFORM, making the display of 
data tricky. To do it effectively requires several steps.
    1) The new subform must be swapped in using OBJECT SET SUBFORM.
    2) A trigger must be set to cause the execution pointer to return to a 
method set the values to be displayed on the form. SET TIMER and CALL PROCESS 
are two such trigger setters.
    3) The execution pointer returned to 4D runtime.
    4) The fields or variables of the subform populated.
    5) The execution pointer returned to 4D runtime.”

Tech Tip: How to dynamically load a Subform and instantly display data (2014) <>

Shows the use of SET TIMER and On Timer. It uses EXECUTE METHOD IN SUBFORM to 
populate the subform. The other way would be to change the subform container 
variable and use On Bound Variable Change

Tech Tip: Required property for On Activate and On Deactivate event of a 
subform (2013) <>

The On Activate and On Deactivate event are used to execute a procedure when a 
form becomes active or inactive state. When a form is used as a subform, the 
Focusable property must be checked for the subform object. The Focusable 
property allows the subform to respond to the right active event.

Tech Tip: Change Page of a Subform (2012) <>
Discussed interaction of FORM GOTO PAGE and FORM Get current page with forms 
and subforms

Tech Tip: How to call methods on the parent form from a subform (2012) <>

I think it still works but I would strongly recommend against using POST KEY to 
communicate to a parent form from a subform

Tech Tip: TimePicker widget can only be modified if placed on page 0 or 1 of 
the form <>

Actually, the note is not complete. The widget has to be modified after it has 
received the On Load event. On Page 0 and 1, this event occurs prior to any 
parent form event. On other pages, the subform’s On Load event only occurs when 
the page is displayed OR when OBJECT SET SUBFORM is executed (after the 
execution cycle of the method using OBJECT SET SUBFORM)

iNug: Re: overlapping subforms <>
A note from Kirk Brooks about subform events:

Also, if you have an input form that allows you to navigate through some 
records (next, previous, etc) and you have a subform on it the subform form 
method will only fire the first time the parent form loads. It DOES NOT fire 
each time you change records like the parent form does. This can be very 

iNug: Re: subforms and object focus
Discussion of how to use GOTO AREA in a subform, initiated from the parent form.

iNug: Re: OBJECT SET SUBFORM - Bug or standard behavior?

iNug: Re: Widget questions (2017) Keisuke Miyako (edited a bit for punctuation)
“…the widget is destroyed when you leave the page, but the variables are not, 
because their scope is the form or process, so you need to differentiate 
between the first and subsequent occurrences of "On Load”. You can do that with 
a "flag" variable, kind of "pragma once" signal inside the widget, but that is 
not all. 

Normally, when you resize the window, all objects on pages that are not 
currently displayed are also logically resized, so their size and position are 
adjusted according to their resize property (grow or move) when you switch to 
that page. However, inner objects of a widget cannot respond to form resize 
events while a different page is displayed, because the parent object (the 
subform container) exists but the inner objects do not. So, when you switch 
pages, you need to update the size and position of each inner object of a 
widget according to its container size, which might have changed while a 
different page was being displayed. So as you might have guessed, this applies 
to page 1 as well. If you move to a second page, the widget on page 1 is 
destroyed (not the variables) and the resizing can go out of sync, so really, 
it is not good enough to keep all widgets on page 0 or 1, it is also important 
to not have multiple pages (or otherwise fix the window size).

Widgets can go any number of levels deep, so I think it is reasonable that 4D 
does not bubble and capture events for all widgets on all levels on all pages…”

4D Internet Users Group (4D iNUG)

Reply via email to