Skip to content

Working with Dynamic Web Objects

Related topics

Introduction

In this section we explain how dynamic objects function and how you can integrate them into your own applications. Please read this section entirely, as there are some crucial steps in the process of using dynamic objects that slightly differ from standard DataFlex practices.

Definitions

We introduce terminology used throughout this documentation and in related presentations.

  • Dynamic objects refer to DataFlex objects that are created at runtime. More specifically, the actual properties of these objects are only loaded when the objects are first initialized. This means the properties can, for instance, be stored in a database and differ per user.
  • Dynamic properties are the initial property values that make up the definition of a dynamic object. Two dynamic objects based on the same DataFlex class can have different property values when they are first created. Dynamic properties override property values set in the Construct_Object procedure of an object.
  • The dynamic container is the container object in which all dynamic objects reside. An application can have multiple dynamic containers, as each container manages its own children.
  • Resetting the dynamic container completely clears it. This means all dynamic objects are destroyed and their definitions are removed from memory.
  • Registering dynamic objects refers to the process of registering a dynamic object with the dynamic container. During this process the object’s dynamic properties are set and the object’s final definition is stored.
  • Activation of the dynamic container indicates that all dynamic objects that have been registered up until that point will now be sent to the client, where they are rendered and displayed.
  • The process of registering dynamic objects occurs in two distinct phases:
  • Creation phase: the first set of dynamic objects are registered and loaded. These objects must be registered sequentially because the order in which they are registered determines the order in which they are displayed. The creation phase ends when the container is activated.
  • Modification phase: begins after the creation phase ends. During this phase, new dynamic objects can be inserted into the existing structure of dynamic objects, or existing dynamic objects can be modified. This phase does not end; the only way to return to the creation phase is by completely resetting the dynamic container.

Creating Dynamic Objects

The process of creating dynamic objects in a web application contains the following steps:

  1. Create an instance of cWebDynamicObjectContainer.
  2. Define object-specific behavior (functions and procedures).
  3. Creation phase.
  4. Activation of the container.
  5. Modification phase.

The following subsections elaborate on these five steps. Small code snippets are included to illustrate usage.

Creating a Dynamic Object Container

Dynamic objects exist inside a specialized container: the cWebDynamicObjectContainer. Creating an instance of this object works just like instantiating any other type of object. The class functions like a cWebGroup and therefore supports basic container properties such as pbScroll and piColumnCount. Example:

Object oContainer is a cWebDynamicObjectContainer
    Set piColumnSpan to 12
    Set piColumnCount to 12
End_Object

Note: the container itself should not contain any static child objects; these will be added at runtime.

Defining Object Behavior

Not every dynamic object behaves the same. Suppose you have two buttons that react differently when clicked by the user. They may look the same, but their behavior is not. Due to the nature of the DataFlex language, it is not possible to dynamically define functions and assign them to classes or objects at runtime. Therefore, to define object-specific behavior for dynamic objects, create a subclass of the object you wish to instantiate dynamically. Use this subclass to outline the specific behavior the dynamic object should have. Later, dynamic objects will be created according to this subclass definition and thus inherit the behavior. Inside the subclass you can also define new properties. All dynamic objects of that subclass will support the new properties.

Example subclass definition for a button with a single new property called piCounter (extends cWebButton):

Class cMyWebButton is a cWebButton
    Procedure Construct_Object
        Forward Send Construct_Object
        { WebProperty=Client }
        Property Integer piCounter 0
        Set piColumnSpan to 8
    End_Procedure
End_Class

Creation Phase

Registering a new Dynamic Object

Now that the dynamic container is set up and the dynamic objects have a definition, dynamic objects can be registered. This phase is called the creation phase. Use the CreateDynamicObject function, defined in the cWebDynamicObjectContainer class, to register a dynamic object. This procedure has the following signature:

Procedure CreateDynamicObject Integer iClassId String sDynamicObjectId String sParentId Returns Handle.
  • iClassId refers to the Class ID of the class that the object should be an instance of (RefClass is often used here).
  • sDynamicObjectId must be a unique identifier for the dynamic object; a single dynamic container cannot contain two objects with the same ID.
  • If an object is located at the root of the dynamic container (i.e., it has no dynamic parent) sParentId should be an empty string.

Example:

Get CreateDynamicObject of oContainer (RefClass(cMyWebButton)) "oMyWebButton" "" to hoObj

Note: during the creation phase all dynamic objects you create will be inserted sequentially. If you want object A to be displayed before object B (under the same parent), create A first.

Setting Dynamic Properties

Dynamic properties allow multiple dynamic objects based on the same subclass to have distinct properties. For regular DataFlex objects, properties are often defined inside the Construct_Object procedure or during object creation. This is not possible for dynamic objects because their property values might not be known at compile time. The Dynamic Object Library supports dynamic properties to solve this issue. Dynamic properties contain property values that differ from the default values set in the subclass definition. Use the InitDynamicProp procedure (defined in cWebObject) to set a dynamic property value:

Procedure InitDynamicProp String sPropName Variant vPropValue

Example: create two buttons based on the same subclass but with different captions:

Get CreateDynamicObject of oContainer (RefClass(cWebGroup)) "oGroup1" "" to hoGroup1
Send InitDynamicProp of hoGroup1 "piColumnCount" 8

Get CreateDynamicObject of oContainer (RefClass(cMyWebButton)) "oButton1" "" to hoButton1
Send InitDynamicProp of hoButton1 "psCaption" "Button 1"

Get CreateDynamicObject of oContainer (RefClass(cMyWebButton)) "oButton2" "" to hoButton2
Send InitDynamicProp of hoButton2 "psCaption" "Button 2"

Each dynamic object can have different initial property values.

Displaying Dynamic Objects

To render the objects, call the Activate procedure included in the cWebDynamicObjectContainer class. This function will send the contents of the dynamic container to the client, which will render all the objects.

Modification Phase

After the dynamic container is activated and its contents are shown to the user, you may need to update the structure of dynamic objects or register new ones. This happens during the modification phase. Currently, the library supports inserting new dynamic objects. Moving or destroying existing dynamic objects is available (see below), while additional features may be added later.

Inserting New Dynamic Objects

Inserting a new dynamic object is similar to registering one in the creation phase:

  1. Register and create the dynamic object (CreateDynamicObject).
  2. Set dynamic properties (InitDynamicProp).
  3. If the object has child objects, create them now.
  4. Insert the new object into the current structure.

Only a single dynamic object (and all its children) can be inserted at once. To insert multiple top-level dynamic objects, call the procedure multiple times.

Procedure:

Procedure InsertAfter String sDynamicObjectId String sInsertAfter

Example: insert a new cWebGroup after an existing group:

Get CreateDynamicObject of oContainer (RefClass(cWebGroup)) "oGroup2" "" to hoGroup2
Send InitDynamicProp of hoGroup2 "piColumnCount" 8

Get CreateDynamicObject of oContainer (RefClass(cWebForm)) "oForm" "oGroup2" to hoForm
Send InitDynamicProp of hoForm "piColumnSpan" 8
Send InitDynamicProp of hoForm "psLabel" "Test Input"

Send InsertAfter of oContainer "oGroup2" "oGroup1"

New dynamic objects can be inserted into the object structure at runtime.

Inserting New Dynamic Objects at a Specific Location

To insert a newly created dynamic object at a specific location (for example, as the fifth child), use:

Procedure InsertDynamicObjectAtIndex String sDynamicObjectId String sParentId Integer iInsertIndex

Be cautious: this procedure assumes you know the structure. In most cases, usage of InsertAfter suffices.

Prepending New Dynamic Objects

To always insert a new object at the front of its parent’s child list, use:

Procedure PrependDynamicObject String sDynamicObjectId

(Used by the Simple Widgets demo to prepend widgets.)

Appending New Dynamic Objects

To append a new object at the end of its parent’s child list, use:

Procedure AppendDynamicObject String sDynamicObjectId

(Used by the Simple Widgets demo to append widgets.)

Moving Existing Dynamic Objects

Moving dynamic objects follows a similar workflow to insertion. The cWebDynamicObjectContainer class provides:

Procedure MoveDynamicObject String sDynamicObjectId String sInsertAfter

The moved object must already exist in the container. The moved object inherits the parent structure of the object it is moved after.

Example: move the dynamic object "Group 1" to after "Group 2":

Send MoveDynamicObject of oContainer "Group 1" "Group 2"

Moving Existing Dynamic Objects to a Specific Location

To move an object to a specific index in its parent’s child list, use:

Procedure MoveDynamicObjectToIndex String sDynamicObjectId String sParentId Integer iInsertIndex

Inserting at an index that already holds a dynamic object shifts the existing object to the next index. (Used by the Questionnaire demo to reorder questions.)

Destroying Existing Dynamic Objects

To completely remove a dynamic object (including its properties and children), use:

Procedure DestroyDynamicObject String sDynamicObjectId

Note: destroying a dynamic object automatically destroys its children.

Using Dynamic Objects

Getting a Dynamic Object

After creating and registering dynamic objects they can be used in your application. Because dynamic objects might not be present in the web server process memory (due to process pooling), retrieve the actual object handle from the dynamic container before calling its procedures. Use:

Function DynamicObject String sDynamicObjectId

This returns the handle for the given dynamic object ID. If the object is not present in the current process, the Dynamic Object Library reconstructs the object according to the stored definition.

Example:

Get DynamicObject of oContainer "oMyWebButton" to hoButton
Send DoStuff of hoButton

Executing actions with or on dynamic objects requires this extra step.

Getting and Setting Properties

Getting and setting properties on dynamic objects uses the same WebGet and WebSet commands as for regular objects. The framework handles synchronization between the server and the client.

Example: extend the previous cMyWebButton subclass with an OnClick procedure that increments a synchronized property:

Class cMyWebButton is a cWebButton
    Procedure Construct_Object
        Forward Send Construct_Object
        { WebProperty=Client }
        Property Integer piCounter 0
        Set piColumnSpan to 8
    End_Procedure

    Procedure IncrementCounter
        Integer iCounter
        WebGet piCounter to iCounter
        Increment iCounter
        WebSet piCounter to iCounter
    End_Procedure

    Procedure OnClick
        Send IncrementCounter
    End_Procedure
End_Class

When to Load Dynamic Objects

Dynamic objects can be loaded at any time by following the steps above. If you want dynamic objects to appear as soon as a view is loaded:

  • For drilldown theme styles: define the creation of dynamic objects inside Procedure OnBeforeShow on the cWebView class.
  • For regular theme styles: define the creation inside Procedure OnLoad of your regular web objects.

See also