Subformulario
Un subformulario es un formulario incluido en otro formulario.
Terminología
Con el fin de definir claramente los conceptos implementados con los subformularios, aquí hay algunas definiciones para ciertos términos utilizados:
- Subformulario: un formulario destinado a ser incluido en otro formulario, llamado a su vez formulario padre.
- Formulario padre: un formulario que contiene uno o más subformularios.
- Contenedor de subformulario: un objeto incluido en el formulario padre, que muestra una instancia del subformulario.
- Instancia de subformulario: la representación de un subformulario en un formulario padre. Este concepto es importante porque es posible mostrar varias instancias del mismo subformulario en un formulario padre.
- Formulario listado: instancia de subformulario mostrada como una lista.
- Formulario detallado: formulario de entrada tipo página asociado a un subformulario tipo lista al que se accede haciendo doble clic en la lista.
Sub-formularios en lista
Un subformulario lista le permite introducir, ver y modificar datos en otras tablas. Normalmente se utilizan subformularios lista en bases de datos en las que se han establecido relaciones Uno a Muchos. Un subformulario lista en un formulario de una tabla Uno relacionada le permite ver, introducir y modificar datos en una tabla Muchos relacionada. Puede tener varios subformularios procedentes de diferentes tablas en el mismo formulario. Sin embargo, no es posible colocar dos subformularios que pertenecen a la misma tabla en la misma página de un formulario.
Por ejemplo, una base de datos del gestor de contactos puede utilizar un subformulario lista para mostrar todos los números de teléfono de un contacto. Aunque los números de teléfono aparecen en la pantalla Contactos, la información se almacena realmente en una tabla relacionada. Utilizando una relación de Uno a Muchos, este diseño de base de datos facilita el almacenamiento de un número ilimitado de números de teléfono por contacto. Con las relaciones automáticas, se puede soportar la entrada de datos directamente en la tabla Muchos relacionada sin programar.
Aunque los subformularios lista suelen estar asociados a muchas tablas, una instancia de subformulario puede mostrar los registros de cualquier otra tabla de la base de datos.
También puede permitir que el usuario introduzca datos en el formulario lista. Dependiendo de la configuración del subformulario, el usuario puede mostrar el formulario detallado haciendo doble clic en un subregistro o utilizando los comandos para añadir y editar subregistros.
4D ofrece tres acciones estándar para satisfacer las necesidades básicas de gestión de los subregistros:
Edit Subrecord
,Delete Subrecord
yAdd Subrecord
. Cuando el formulario incluye varias instancias de subformulario, la acción se aplicará al subformulario que tenga el foco.
Sub-formularios en página
Los subformularios en modo página pueden mostrar los datos del subregistro actual o todo valor pertinente en función del contexto (variables, imágenes, etc.). Una de las principales ventajas de utilizar subformularios página es que pueden incluir funcionalidades avanzadas y pueden interactuar directamente con el formulario padre (widgets). Los subformularios en página también tienen sus propiedades y eventos específicos; puede gestionarlos completamente por programación.
El subformulario en página utiliza el formulario de entrada indicado por la propiedad Formulario detallado. A diferencia de un subformulario en modo lista, el formulario utilizado puede proceder de la misma tabla que el formulario padre. También es posible utilizar un formulario proyecto. Cuando se ejecuta, un subformulario en modo página tiene las mismas características de visualización estándar que un formulario de entrada.
Los widgets 4D son objetos compuestos predefinidos basados en subformularios página. They are described in detail in a separate manual, 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
andOBJECT 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 representing a clock, inserted into a parent form containing an enterable variable of the Time type:
In the parent form, both objects (time variable and subform container) ***have the same value as ***Variable or Expression******. It can be a variable (e.g. parisTime
), or an expression (e.g. Form.parisTime
).
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.
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 Current time
command 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:
The On Bound Variable Change form event is generated:
- as soon as a value is assigned to the variable/expression of the parent form, even if the same value is reassigned
- si el subformulario pertenece a la página formulario actual o a la página 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
Caso 2: se modifica el contenido del subformulario y esta modificación debe pasar al formulario padre.
Inside the subform, the button changes the value of the Form.clockValue
expression of type Time attached to the clock object. This triggers the On Data Change form event inside the clock object (this event must be selected for the object), which updates the Form.parisTime
value in the main form.
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, 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.
Programación entre formularios avanzada
Communication between the parent form and the instances of the subform may require going beyond the exchange of a values through the bound variable. De hecho, es posible que desee actualizar las variables de los subformularios en función de las acciones realizadas en el formulario principal y viceversa. Si utilizamos el ejemplo anterior del subformulario de tipo "reloj dinámico", es posible que queramos definir una o varias horas de alarma para cada reloj.
4D ha implementado los siguientes mecanismos para satisfacer estas necesidades:
- Calling of a container object from the subform using the
CALL SUBFORM CONTAINER
command - Execution of a method in the context of the subform via the
EXECUTE METHOD IN SUBFORM
command
El comando
GOTO OBJECT
busca el objeto de destino en el formulario padre aunque se ejecute desde un subformulario.
Comando 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. El evento se recibe en el método del objeto contenedor. Puede estar en el origen de todo evento detectado por el subformulario (clic, arrastrar y soltar, etc.).
El código del evento no tiene restricciones (por ejemplo, 20000 o -100). Puede utilizar un código que corresponda a un evento existente (por ejemplo, 3 para On Validate
), o utilizar un código personalizado. En el primer caso, sólo puede utilizar los eventos que haya marcado en la lista de propiedades para los contenedores de subformulario. En el segundo caso, el código no debe corresponder a ningún evento de formulario existente. Se recomienda utilizar un valor negativo para asegurarse de que este código no será utilizado por 4D en futuras versiones.
Para más información, consulte la descripción del comando CALL SUBFORM CONTAINER
.
Comando EXECUTE METHOD IN SUBFORM
El comando EXECUTE METHOD IN SUBFORM
permite que un formulario o uno de sus objetos solicite la ejecución de un método en el contexto de la instancia del subformulario, lo que le da acceso a las variables, objetos, etc. del subformulario. Este método también puede recibir parámetros.
Este mecanismo se ilustra en el siguiente diagrama:
Para más información, consulte la descripción del comando EXECUTE METHOD IN SUBFORM
.
Propiedades soportadas
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