Aller au contenu principal
Version: v20

Sous-formulaire

Un sous-formulaire est un formulaire inclus dans un autre formulaire.

Terminologie

Afin de bien définir les notions mises en oeuvre avec les sous-formulaires, voici quelques définitions relatives aux termes employés :

  • Sous-formulaire : formulaire destiné à être inclus dans un autre formulaire, lui-même nommé formulaire parent.
  • Formulaire parent : formulaire contenant un ou plusieurs sous-formulaire(s).
  • Conteneur de sous-formulaire : objet inclus dans le formulaire parent, contenant une instance du sous-formulaire.
  • Instance de sous-formulaire : la représentation d’un sous-formulaire dans un formulaire parent. Cette notion est importante car il est possible d’afficher plusieurs instances d’un même sous-formulaire dans un formulaire parent.
  • Formulaire liste écran : instance de sous-formulaire en liste.
  • Formulaire détaillé : formulaire de saisie en page associé au sous-formulaire en liste et accessible via un double-clic dans la liste.

Sous-formulaires en liste

Un sous-formulaire en liste vous permet de saisir, visualiser et modifier des données dans d’autres tables. Les sous-formulaires en liste sont généralement utilisés avec les bases de données utilisant des liens de type 1 vers N. Un sous-formulaire en liste affiche les enregistrements de la table N liée par un lien automatique de type 1 vers N. Vous pouvez disposer de plusieurs sous-formulaires provenant de différentes tables dans le même formulaire. En revanche, il n’est pas possible de placer deux sous-formulaires appartenant à la même table dans une même page de formulaire.

Par exemple, une base de gestion de contacts peut utiliser une instance de sous-formulaire en liste pour afficher tous les contacts d’une société. Bien que les contacts apparaissent dans l’écran général, l’information est en fait stockée dans la table liée. A l’aide d’un lien 1 vers N, la conception de cette base de données rend facile le stockage d’un nombre illimité de contacts pour chacune des sociétés. Avec des liens automatiques, vous pouvez permettre la saisie de données dans la table liée sans programmation.

Bien que les sous-formulaires en liste soient généralement associés aux tables N, une instance de sous-formulaire peut afficher des enregistrements de toute autre table de la base de données.

Vous pouvez également permettre à l’utilisateur de saisir des données dans le formulaire liste. Suivant la configuration du sous-formulaire, l’utilisateur pourra afficher le formulaire détaillé en double-cliquant sur un sous-enregistrement ou en utilisant les commandes d’ajout et de modification des sous-enregistrements.

4D propose trois actions standard, permettant de répondre aux besoins élémentaires de gestion des sous-enregistrements : Modifier sous-enregistrement, Supprimer sous-enregistrement et Ajouter sous-enregistrement. Lorsque le formulaire comporte plusieurs instances de sous-formulaires, l’action s’applique au sous-formulaire ayant le focus.

Sous-formulaires en page

Les sous-formulaires en mode page peuvent afficher des données relatives à l'enregistrement courant ou toute valeur pertinente en fonction du contexte (variables, images, etc.). Il peuvent également, et c'est là leur intérêt majeur, comporter des fonctionnalités avancées et interagir avec le formulaire parent (widgets). Les sous-formulaires en page bénéficient de propriétés et d'événements spécifiques, et peuvent être entièrement contrôlés par programmation.

Le sous-formulaire en page utilise le formulaire entrée désigné par la propriété Formulaire détaillé. A la différence d’un sous-formulaire en mode liste, le formulaire utilisé peut provenir de la même table que le formulaire parent. Il est également possible d’utiliser un formulaire projet. En exécution, un sous-formulaire en mode page dispose des caractéristiques d’affichage standard d’un formulaire entrée.

Les widgets 4D sont des objets composés prédéfinis. Ils sont décrits en détail dans le manuel 4D Widgets.

Using the bound variable or expression

You can bind a variable or an expression to a subform container object. This is very useful to synchronize values from the parent form and its subform(s).

By default, 4D creates a variable or expression of object type for a subform container, which allows you to share values in the context of the subform using the Form command (see below). However, you can use a variable or expression of any scalar type (time, integer, etc.) especially if you only need to share a single value:

  • Define a bound variable or expression of a scalar type and call the OBJECT Get subform container value and OBJECT SET SUBFORM CONTAINER VALUE commands to exchange values when On Bound Variable Change or On Data Change form events occur. This solution is recommended to synchronize a single value.
  • Define a bound variable or expression of the object type and use the Form command to access its properties from the subform. This solution is recommended to synchronize several values.

Synchronizing parent form and subform (single value)

Binding the same variable or expression to your subform container and other objects of the parent form lets you link the parent form and subform contexts to put the finishing touches on sophisticated interfaces. Imagine a subform that contains a clock displaying a static time, inserted into a parent form containing an input area:

Dans le formulaire parent, les deux objets (zone de saisie et conteneur de sous-formulaire) ont la même valeur que Variable ou expression**. It can be a variable (e.g. parisTime), or an expression (e.g. Form.parisTime).

info

To display a static time, you must use the appropriate data type for the variable or expression:

  • If you use a variable (e.g. parisTime), it must be of the text or time type.
  • If you use an expression (e.g. Form.myValue), it must contain a text value.

The text value must be formatted "hh:mm:ss".

In the subform, the clock object is managed through the Form.clockValue property.

Updating the contents of a subform

Case 1: The value of the parent form variable or expression is modified and this modification must be passed on to a subform.

parisTime or Form.parisTime changes to "12:15:00" in the parent form, either because the user entered it, or because it was updated dynamically (via the String(Current time) statement for example). This triggers the On Bound Variable Change event in the subform's Form method.

The following code is executed:

// Subform form method
If (Form event code=On Bound Variable Change) //bound variable or expression was modified in the parent form
Form.clockValue:=OBJECT Get subform container value //synchonize the local value
End if

It updates the value of Form.clockValue in the subform:

L’événement formulaire Sur modif variable liée est généré :

  • as soon as a value is assigned to the variable/expression of the parent form, even if the same value is reassigned
  • si le sous-formulaire appartient à la page formulaire courante ou à la page 0.

Note that, as in the above example, it is preferable to use the OBJECT Get subform container value command which returns the value of the expression in the subform container rather than the expression itself because it is possible to insert several subforms in the same parent form (for example, a window displaying different time zones contains several clocks).

Modifying the bound variable or expression triggers form events which let you synchronize the parent form and subform values:

  • Use the On Bound Variable Change form event to indicate to the subform (form method of subform) that the variable or expression was modified in the parent form.
  • Use the On Data Change form event to indicate to the subform container that the variable or expression value was modified in the subform.

Updating the contents of a parent form

Scénario 2 : Le contenu du sous-formulaire est modifié et cette modification doit être répercutée dans le formulaire parent.

Dans le sous-formulaire, le bouton modifie la valeur de l'expression Form.clockValue de type Texte attachée à l'objet horloge. Cela déclenche l'événement formulaire On Data Change dans l'objet horloge (cet événement doit être sélectionné pour l'objet), qui met à jour la valeur Form.parisTime dans le formulaire principal.

The following code is executed:

// subform clock object method
If (Form event code=On Data Change) //whatever the way the value is changed
OBJECT SET SUBFORM CONTAINER VALUE(Form.clockValue) //Push the value to the container
End if

Everytime the value of Form.clockValue changes in the subform, parisTime or Form.parisTime in the subform container is also updated.

If the variable or expression value is set at several locations, 4D uses the value that was loaded last. It applies the following loading order: 1-Object methods of subform, 2-Form method of subform, 3-Object methods of parent form, 4-Form method of parent form

Synchronizing parent form and subform (multiple values)

By default, 4D binds a variable or expression of object type to each subform. The contents of this object can be read and/or modified from within the parent form and from the subform, allowing you to share multiple values in a local context.

When bound a the subform container, this object is returned by the Form command directly in the subform. Since objects are always passed by reference, if the user modifies a property value in the subform, it will automatically be saved in the object itself and thus, available to the parent form. On the other hand, if a property of the object is modified by the user in the parent form or by programming, it will be automatically updated in the subform. No event management is necessary.

For example, in a subform, inputs are bound to the Form object properties (of the subform form):

In the parent form, you display the subfom twice. Each subform container is bound to an expression which is a property of the Form object (of the parent form):

The button only creates mother and father properties in the parent's Form object:

//Add values button object method
Form.mother:=New object("lastname"; "Hotel"; "firstname"; "Anne")
Form.father:=New object("lastname"; "Golf"; "firstname"; "Félix")

When you execute the form and click on the button, you see that all values are correctly displayed:

If you modify a value either in the parent form or in the subform, it is automatically updated in the other form because the same object is used:

Using pointers (compatibility)

In versions prior to 4D v19 R5, synchronization between parent forms and subforms was handled through pointers. For example, to update a subform object, you could call the following code:

// Subform form method
If (Form event code=On Bound Variable Change)
ptr:=OBJECT Get pointer(Object subform container)
clockValue:=ptr->
End if

This principle is still supported for compatibility but is now deprecated since it does not allow binding expressions to subforms. It should no longer be used in your developments. In any cases, we recommend to use the Form command or the OBJECT Get subform container value and OBJECT SET SUBFORM CONTAINER VALUE commands to synchronize form and subform values.

Programmation inter-formulaires avancée

Communication between the parent form and the instances of the subform may require going beyond the exchange of a values through the bound variable. En effet, vous pouvez souhaiter mettre à jour des variables dans les sous-formulaires en fonction d’actions effectuées dans le formulaire parent et inversement. Si l’on reprend l’exemple du sous-formulaire de type "pendule dynamique", on peut souhaiter définir une ou plusieurs heures d’alerte par pendule.

Pour répondre à ces besoins, 4D propose les mécanismes suivants :

  • Appel de l’objet conteneur depuis le sous-formulaire via la commande CALL SUBFORM CONTAINER
  • Exécution d’une méthode dans le contexte du sous-formulaire via la commande EXECUTE METHOD IN SUBFORM

La commande GOTO OBJECT peut rechercher l’objet de destination dans le formulaire parent même si elle exécutée depuis un sous-formulaire.

Commande CALL SUBFORM CONTAINER

The CALL SUBFORM CONTAINER command lets a subform instance send an event to the subform container object, which can then process it in the context of the parent form. L’événement est reçu dans la méthode de l’objet conteneur. Il peut s’agir à l’origine de tout événement détecté par le sous-formulaire (clic, glisser-déposer, etc.).

Le code de l’événement est libre (par exemple, 20000 ou -100). Vous pouvez soit utiliser un code correspondant à un événement existant (par exemple, 3 pour Sur validation), soit utiliser un code personnalisé. Dans le premier cas, seuls les événements présents dans la liste des événements "cochables" des conteneurs de sous-formulaire peuvent être utilisés (cf. Liste des propriétés). Dans le second cas, le code ne doit correspondre à aucun événement formulaire existant. Il est conseillé d’utiliser une valeur négative pour avoir l’assurance que 4D n’utilisera pas ce code dans les versions futures.

Pour plus d'informations, reportez-vous à la description de la commande CALL SUBFORM CONTAINER.

Commande EXECUTE METHOD IN SUBFORM

La commande EXECUTE METHOD IN SUBFORM permet à un formulaire ou à l’un de ses objets de demander l’exécution d’une méthode dans le contexte de l’instance du sous-formulaire, ce qui lui donne accès aux variables, objets, etc., du sous-formulaire. Cette méthode peut en outre recevoir des paramètres.

Ce mécanisme est illustré dans le schéma suivant :

Pour plus d'informations, reportez-vous à la description de la commande EXECUTE METHOD IN SUBFORM.

Propriétés prises en charge

Border Line Style - Bottom - Class - Detail Form - Double click on empty row - Double click on row - Enterable in list - Expression Type - Focusable - Height - Hide focus rectangle - Horizontal Scroll Bar - Horizontal Sizing - Left - List Form - Method - Object Name - Print Frame - Right - Selection mode - Source - Top - Type - Variable or Expression - Vertical Scroll Bar - Vertical Sizing - Visibility - Width