This page documents all the properties and methods on the Dynamic Form and Dynamic Form Render Engine classes.
Note: The DynamicForm class uses an instance of the DynamicFormRenderEngine class to do all the real work behind the scenes.
Most basic usage of a Dynamic Form can be accomplished by working on properties and methods on the DynamicForm instance which you create at run time. However, some of the more detailed or advanced settings must be accessed though the oRenderEngine object that lives on the DynamicForm instance. This oRenderEngine object is created automaticllay by the DynamicForm instance when it it created, so it will be alive and ready to respond to your settings as you make them. You access the oRenderEngine object as follows:loForm.oRenderEngine
Note: Many of the properties defined on the form are merely wrappers which will eventually be passed on to the RenderEngine class. They are hosted on the form simply as a convenience for coding.
DynamicForm Class – Properties
Property name | Default value | Description |
cAlias | (empty) | (Optional) The cursor/alias to which the controlsources in the cBodyMarkup will be bound. Make sure this alias is opened and positioned at this correct record. Note: If you need to bind form fields to more than one cursor, simply include the cursor/alias in the controlsource markup along with the field name. I.e.“MyTable1.field1 | MyTable2.Field1” (See Step 1 on main page) |
oDataObject | .NULL. | (Optional) Build or populate an object with data properties, then pass it in to this oDataObject property. The controlsource for each field in the cBodyMarkup will now bind to this oDataObject. (See Step 1 on main page) |
oBusinessObject | .NULL. | (Optional) A Business Object that has a data access methods which can be called to save the changes to the oDataObject. See Using Dynamic Forms with Business Objects. |
cBusinessObjectSaveMethod | (empty) | (Optional) A string indicating the method and any parameters that are to be called on oBusinessObject to save the oDataObject when the user clicks the Save button. See Using Dynamic Forms with Business Objects. |
cHeading | (empty) | (Optional) The label caption to be used in the Header area. |
nHeadingFontSize | 14 | The fontsize for the label in the Header area. |
cSaveButtonCaption | .NULL. | The caption to be displayed in the Save button in the footer area. |
cCancelButtonCaption | .NULL. | The caption to be displayed in the Cancel button in the footer area. |
cHeaderMarkup | (see desc) | The markup syntax used to render the Header area. See Header/Body/Footer Diagram for more info and default layout. |
cBodyMarkup | The markup syntax used to render the main Body area. See Header/Body/Footer Diagram for more info. | |
cFooterMarkup | (see desc) | The markup syntax used to render the Footer area. See Header/Body/Footer Diagram for more info and default layout. |
cReturn | You can get custom return values from the Dynamic Form using instances of the default “commandbutton” class, which resolves to the custom DF_ResultButton class by default. Using these command buttons, when the button is clicked, the form will hide and the
caption of the command button will be passed to the loForm.cReturn property (any hotkey characters in the caption will be removed). This allows you to easily test loForm.cReturn to see which of command button was clicked, and you can take the appropriate action
as control passes back to the calling program. See Step 7 on main page for more info. | |
lRestoreDataOnCancel | .T. | When .T., changes to all controlsource data bindings will be restored to their original values if form Cancelled by user. This applies to cAlias fields, oDataObjectProperties, and private/public variables, as well as any other directly
referenced aliases via the controlsource. See the aBackup[] array property on the Render Engine class for where these values are stored, and see BackupData() and RestoreData() on the Render Engine class. |
lClearEventsOnClose | .F. | In case want Dynamic Form to call Clear Events when the form is closed via Save, Cancel, or the [X] close button. |
lSaveClicked | .F. | Indicates if the Save button was clicked by the user. (See Step 7 on main page) |
lCancelClicked | .F. | Indicates if the Cancel button was clicked by the user. (See Step 7 on main page) |
oRenderEngine | The form class will create and use an instance of the DynamicFormRenderEngine class to do all the rendering work. The RenderEngine object is stored in this oRenderEngine property. If you wish to override any of the DynamicFormRenderEngine poperties or methods, you can do so by following the instructions in Subclassing DynamicForm. |
DynamicForm Class – Methods
Method Name | Parameters | Description |
Render() | (none) | It is not necessary to call this method, as you can call the Show() method directly to display the form immediately. However, this method can be used to pre-render the controls into the form’s container in order to check for rendering
or binding errors before attempting to display the form. This method returns a Boolean value indicating if the render process completed without errors. This method can be used when you want to pre-render the form to check for errors before calling the Show()
method. The form is not displayed until *you* call the Show() method. Any rendering errors are usually caused by errors in your cBodyMarkup markup string. Rendering Errors - If the Render() methods returns .F., this means there were rendering errors, which you can read from loForm.oRenderEngine.nErrorCount and you can get and error list in a string format by calling loForm.oRenderEngine.GetErrorsAsString(), or get details on every error from the loForm.oRenderEngine.oErrors collection. Learn more aboutrendering errors here. Even with rendering errors, the form can still be displayed to the user if desired. During development, showing the form (even with errors) will help you see where the errors occurred, as it will show a red error container in place of any controls which had rendering errors. |
Show() | tnMode, toFormObject | Display the form to the user by calling loForm.Show(). The default mode is a Modal, which can be overridden to Modeless with parameter tnMode. Modal forms– After calling Show() or Show(1) a Modal form will be presented to the user. When they click Save, Cancel, or the [X] button the Dynamic Form will be hidden and flow will return to the calling program where you can then read any property on loForm and loForm.oRenderEngine, and even access the rendered controls. Note: at this point the form is hidden only, but still alive and accessible via its object reference. So, after control has passed back to the calling program code, you can perform the next steps required based on your application architecture... First, analyze the loForm.cResult value to know which button was clicked, then, for example, perform any data validation, deal with buffered cursors, or call the “save” method on a Business Object. Modeless forms – When calling Show(0) to create a Modeless form, Dynamic Form will add a unique global reference to itself on _screen (I.e. _screen.DF_3LW0JDOD6) so that the form will be kept alive even after control has passed back to the
calling code and the local form reference eventually falls out of scope. From here your Dynamic Form will be released only when the user clicks the Save or Cancel button. When released, the global reference will be removed from _screen and form object will
be cleared from memory. You may want to trap the Save or Cancel user actions by use of BindEvent(). You can bind to loForm.Save() and loForm.Cancel() for this purpose. The methods perform no local actions, and are merely provided as hook points for BindEvent()
as described here. Handling Save and Cancel Buttons– The Save and Cancel buttons will trigger calls to the Save() and Cancel() methods on the form. This architecture allows you subclass DynamicForm to provide your own Save() and Cancel() code, or to hook into these events with a BindEvent() call, if desired, to respond to these user actions when they eventually occur. After triggering the Save() or Cancel() methods on the form, the buttons will Hide the form if it is Modal (see Modal Forms section above), or Release the form if it is Modeless (see Modeless Forms section above). Saving changes
Parameters: tnMode - 0 = Modeless, 1 = Modal (default) toFormObject – You can have the rendered Dynamic Form centered in a hosting form if you pass in a reference to the hosting form when calling the Show() method on Dynamic Form:
|
DynamicFormRenderEngine – Properties
These properties control the visual layout and rendering flow that happens by the Render Engine.
You access these properties in the following way: loForm.oRenderEngine.PropertyName
Note: It is recommended that you follow the subclassing guidelines to create your own classes for DynamicForm and DynamicFormRenderEngine so that you can easily override any of these default values to suite your own usage and form designs.
Property Name | Default Value | Description / Notes |
cAlias | (empty) | The name of a cursor or alias to which the cBodyMarkup controls are bound. |
oDataObject | .NULL. | The object to which the cBodyMarkup controls are bound. |
oBusinessObject | .NULL. | (Optional) A Business Object that has a data access methods which can be called to save the changes to the oDataObject. See Using Dynamic Forms with Business Objects. |
cBusinessObjectSaveMethod | (empty) | (Optional) A string indicating the method and any parameters that are to be called on oBusinessObject to save the oDataObject. See Using Dynamic Forms with Business Objects. |
cBodyMarkup | .NULL. | This is the “markup syntax” string which defines fields, control classes, and other attributes to define the layout of the form.
If cBodyMarkup remains .null. at run time, then all properties from oDataObject or all fields from cAlias will be displayed. You can specify fields to skip using the cSkipFields property. See Markup Syntax guide for details. See Form Layout Diagram for more details. |
cHeaderMarkup | .NULL. | The layout markup for the Header area of the form. If .null. at run time, the default Header markup from GetHeaderMarkup() method will be used. This Header markup is appended to the beginning of cBodyMarkup. The default Header markup
includes label and a horizontal line. You can set this property to your own custom Header markup, or set it to an empty string to omit any Header from the rendered form. See Footer and Header Diagram for more details. |
cFooterMarkup | .NULL. | The layout markup for the Footer area of the form. If .null. at run time, the default Footer markup from GetFooterMarkup() method will be used. This Footer markup is appended to the end of cBodyMarkup. The default Footer markup
includes a horizontal line, a Save button and a Cancel button. You can set this property to your own custom Footer markup, or set it to an empty string to omit any Footer from the rendered form. See Footer and Header Diagram for more details. |
cHeading | (empty) | A string that is used by the cHeaderMarkup layout to set the caption of the form heading label. |
nHeadingFontSize | 12 | The fontsize for the form heading label. Used in the cHeaderMarkup string to size the label. |
cSaveButtonCaption | .NULL. | The caption to be displayed in the Save Button in the footer area. |
cCancelButtonCaption | .NULL. | The caption to be displayed in the Cancel Button in the footer area. |
cHeaderMarkup | (see desc) | This is a Header markup which is appended to the beginning of cBodyMarkup. The default Header markup includes label and a horizontal line. Set to (empty) to omit the Header area from the form, or override to create a custom Header. |
cFooterMarkup | (see desc) | This is a default markup string which is appended to the end of cBodyMarkup to add a horizontal line, a Save and Cancel button to form a “Footer” region on the form.
Set to (empty) to omit the Footer area from the form, or override to create a custom Footer. |
cSkipFields | (empty) | Any fields listed here will be skipped when then form is rendered, even if they are listed in cBodyMarkup. Separate each field in this list with a comma or space. |
nControlLeft | (see desc) | The .Left position of the first control on a row. Relative to left edge of form or current column. If lLabelsAbove = .f. (default) , the default nControlLeft value is 120. If lLabelsAbove = .t., the default nControlLeft value is 20. |
nFirstControlTop | (see desc) | The .Top position of the first control on the form, or in the current column. Default = 10 for lLabelsAbove = .F. Default = 30 for lLablesAbove =.T. |
nVerticalSpacing | (see desc) | The vertical spacing between each UI control that has a ControlSource proprty. Note: for control that do not have a ControlSource propert, see nVerticalSpacingNonControlSourceControls . If lAutoAdjustVerticalPositionAndHeight = .F. (default), this value is the distance from the BOTTOM of the last control to the the .Top of the next control. If lLabelsAbove = .F., the default value is 15, else the default is 30 (to make room for the label). If lAutoAdjustVerticalPositionAndHeight = .T., this value is from the .Top of one control to the .Top of the next control. If lLabelsAbove = .F., the default value is 30, else the default is 50. |
nVerticalSpacingNonControlSourceControls | 10 | This property controls the vertical spacing used to render controls that do not have a ControlSource property (i.e. label, line), or if the control baseclass is 'checkbox' and uses lLabelsAbove = .t. These types of controls often do no need or use as much vertical space as, say, a textbox, so it’s often beneficial to set a tighter vertical spacing for these. |
lLabelsAbove | .F. | Default position is for labels to be inline with the input control, to its left. Set this property to .T. to have the labels placed ABOVE the input control. See Field Labels link for more info. |
nCheckBoxAlignment | 0 | 0 = Middle Left (Caption on Right) (Default in VFP) |
nControlHeight | 24 | The .Height of each control that’s generated. Use :height => ‘n’ to override on any given control. |
nHorizontalSpacing | 15 | Horizontal distance between controls when rendering on the same row with :row=increment => '0' |
nHorizontalLabelGap | 8 | The horizontal spacing between the label and the next input control (when labels are inline with controls). |
lAutoAdjustVerticalPositionAndHeight | .F. | Forces the .Top and .Height of each control to “snap” to a grid system based on increments on nControlHeight and nVerticalSpacing. The helps keeps control vertically aligned when form spans two columns or more. When enabling this feature, any .Top and .Height values specified in attributes may be adjusted to “snap” to the grid system at its incremental points. |
nColumnWidth | 200 | The width of each virtual column on the page. See Columns link for more info. |
nColumnHeight | 800 | The host container (a.k.a. “Render surface”) will be resized up to this height before switching to next column
See Columns link for more info, and the Form Layout diagram to understand more about the rendering container. When the Render() method is called, the caller passes in a container reference in which the caller wants controls to be rendered. As the controls are generated, the RenderEngine automatically increases the Height of the passed container, if necessary, to hold the generated controls. Eventually, this container could get VERY TALL, so as to become unusable or even off-screen. This is where nColumnHeight comes in, which says “grow the passed container up to this height, then move over to the next column” Or, said another way, “If the contents reach nColumnHeight, then switch over to the next column” You can avoid the effects of this column-changing behavior simply by setting a really high nColumnHeight in your subclass. |
These properties control default height and width of input controls
The defaults are applied based on the baseclasses.Property Name | Default Value | Description / Notes |
nControlHeight | 24 | The .Height of each control. Use :height => ‘n’ to override. |
nTextBoxWidth | 100 | Default width of textboxes. Use :width => 'n' to override. |
nEditBoxWidth | 200 | Default width of editboxes. Use :width => 'n' to override. |
nNumericFieldTextboxWidth | 100 | Data types of Numeric will be displayed in a textbox of this width Use :width => 'n' to override. |
nCheckBoxWidth | 100 | Default width of checkbox. Use :width => 'n' to override. |
nControlWidth | 100 | Default width for any other controls besides the specific ones above. |
Advanced Properties
Property Name | Default Value | Description / Notes |
cDelimiterPattern | ‘|’ | Caution: Don't use a comma as delimiter. It will likely break things. Default is (pipe symbol). |
cAttributeNameDelimiterPattern | ‘:’ | The delimiter pattern used to denote the beginning of an attribute name. Default is (colon). |
cAttributeValueDelimiterPattern | ‘=>’ | The delimiter pattern used to denote the beginning of an attribute value. Default is => |
oContainer | .NULL. | When calling the Render() method, you pass in an object reference to a container into which you want the controls rendered. This object reference will be stored locally on the RenderEngine in this property. |
cDataObjectRef | (empty) | The reference to the oDataObject to be used in the ControlSource property of each control that gets generated. I.e. 'Thisform.oBusObj.oData' any object with Private or Public scope. |
nErrorCount | 0 | The number of errors encountered by the RenderingEngine when reading and applying the markup syntax. |
oErrors | .NULL. | A collection of error messages encountered by the RenderingEngine when reading and applying the markup syntax. You can get this collection returned as a string list by calling the GetErrorsAsString() method. |
aBackup | .F. | An array which holds the controlsource names from cBodyMarkup and the initial values at render time. This is used as a backup of the initial values so they can later be restored by RestoreData(), if required. Seerestoring data values for more info. |
DynamicFormRenderEngine - Methods
You can access these methods in the following way: loForm.oRenderEngine.MethodName()
The only Render Engine methods that are generally called from the outside are:
Method Name | Parameters | Description / Notes |
Render() | toContainer | This methods processes the cBodyMarkup string to create the individual controls within the passed toContainer. |
RestoreData() | none | Restores the controlsource bindings to their original data values. Seerestoring data values for more info. |
GetErrorsAsString() | none | Returns a string value of any rendering error messages that were triggered during the Render() process. Learn more about rendering errors here. |
GetHeaderMarkup() | none | A method that returns the cHeaderMarkup string to create the “Header” region of the form. |
GetFooterMarkup() | none | A method that returns the cFooterMarkup string to create the “Footer” region of the form. |
Here is a complete list of methods on the DynamicFormRenderEngine class. Most of these methods should be regarded as internal methods, and are not needed externally during regular use.
While most of the rendered layout is controlled by class properties which you can adjust as desired, if you really want to dig deep into the rendering logic to make lower level changes in the layout flow, you could subclass the the DynamicFormRenderEngine and override any of the styling/flow/render-logic methods to suite your particular needs or tastes. Go for it!!