It’s possible to integrate a dynamic form manager and substitute the one that comes by default with GXflow. In this way, you can associate dynamic forms defined in a system external to GXFlow to the tasks of a process; you can also invoke the program in charge of presenting said form during task execution.
You must implement a provider that allows displaying the list of dynamic forms of an external provider at the moment when the user is going to select a form to associate it with a task.

To do this, you must implement a GeneXus Extension. Read the following Getting Started to know more about Extensions.
All the classes and interface that are needed to do this are in the Artech.Gxpm.Common.DynamicForms namespace, and are contained in the Artech.Gxpm.Common.dll that you can find in the root directory of the GeneXus installation.
To create a dynamic form provider, first the class which implements the extension’s IGxPackage interface must implement the IHasCustomDynamicFormsProvider interface as follows:
public interface IHasCustomDynamicFormsProvider
{
IDynamicFormsProvider GetDynamicFormsProvider();
}
The GetDynamicFormsProvider method returns the provider that must implement the IDynamicFormsProvider interface:
public interface IDynamicFormsProvider
{
bool ClientShouldCacheValues { get; }
IEnumerable<DynamicFormHeader> GetForms(KnowledgeBase kb);
DynamicForm GetForm(KnowledgeBase kb, Guid guid, int version);
}
If the ClientShouldCacheValues property returns value True, then it means that all the form metadata will be cached, which means that it’s only asked once to the provider.
The GetForms method returns an enumerated with the metadata from the forms’ headers, DynamicFormHeader has the header’s properties:
Guid Guid
int Version
string Name
The GetForm method returns a specific form’s complete metadata.DynamicForm has two properties:
DynamicFormHeader Header
IEnumerable<DynamicFormElement> Elements
The Elements property returns the metadata of the form’s elements. DynamicFormElement has the following properties:
Guid Guid
int Version
string Name
DynamicFormElementType Type
int Length
DynamicFormElementType is an enumerated with the valid types for an element:
Numeric
Character
Boolean
Date
Datetime
For the GXflow Client application to invoke the external program that will be in charge of showing the dynamic forms, you must go to “Server settings > Application “ and set the Dynamic Forms Provider property with the value “External”. After saving this data, the Dynamic Forms Invoker URL property will appear, where you must configure the complete or relative URL to the web object that will be in charge of displaying the dynamic forms. If you use package (Java generator), include this as well.

The GXflow client will invoke said URL using the GeneXus Link command, and passing the following parameters:
1) Application GUID
2) Code of Process Definition
3) Code of Process Instance
4) Code of Workitem
The parameters will eventually be encrypted according to the configuration of the Knowledge Base properties.
The following source code is an example of a web panel that acts as a form invoker.
parm(in: &ApplicationGUID, in: &processDefinitionId, in: &processInstanceId, in: &workitemId);
Event Start
&WorkflowContext.Load(&processDefinitionId, &processInstanceId, &workitemId)
&WorkflowWorkitem = &WorkflowContext.Workitem
&WorkflowActivity = &WorkflowWorkitem.Activity
For &WorkflowActivityApplication in &WorkflowActivity.Applications
If (&WorkflowActivityApplication.Application.GUID.Trim() = &ApplicationGUID.Trim())
&Type = &WorkflowActivityApplication.Application.Type
If &Type = WorkflowApplicationType.DYNAMIC_FORM
&DynFormFormGuid = Guid.FromString(&WorkflowActivityApplication.Application.GUID.Trim())
&DynFormFormVer = &WorkflowActivityApplication.Version
&WorkflowAttribute = &WorkflowWorkitem.GetAttributeByName(‘FORM_INSTANCE_ID’)
If (&WorkflowAttribute.Value.IsEmpty()) // If a dynamic form instance didn’t exist already
// Generates a new instance of the form with GUID = &DynFormFormGuid
// and version = &DynFormFormVer and saves it in the &DynFormFormInstId variable
...
// Saves the instance’s id as metadata of the workitem in case it’s necessary to invoke it again.
&WorkflowAttribute.Name = ‘FORM_INSTANCE_ID’
&WorkflowAttribute.Value = &DynFormFormInstId.ToString()
&WorkflowWorkitem.AddAttribute(&WorkflowAttribute)
COMMIT
Else // If the instance already exists, retrieves the metadata
&DynFormFormInstId = &WorkflowAttribute.Value.ToNumeric()
EndIf
// Invokes the form with id = &DynFormFormInstId and the necessary data
……..
EndIf
EndFf
Exit
EndFor
EndEvent
If in the diagram there’s mapping between relevant data and fields of the form, it’s necessary that when the form is confirmed, then the relevant data mapped in said fields is updated.
The following code is an example of a procedure that is called after confirming a form to update relevant data that has mapping with fields of the entered form.
//See previous code to know how to retrieve the &WorkflowActivityApplication variable
For &WorkflowDynamicFormFieldMapping in &WorkflowActivityApplication.DynamicFieldMappings
&WorkflowApplicationData = &WorkflowContext.ProcessInstance.GetApplicationDataByName(&WorkflowDynamicFormFieldMapping.ApplicationDataDefinition.Name.Trim())
&DynamicFieldGUID = &WorkflowDynamicFormFieldMapping.DynamicField.GUID.Trim()
&DynamicFieldVersion = &WorkflowDynamicFormFieldMapping.DynamicField.Version
//Obtains the value (&FieldValue) and data type (&FieldValue) of the filed with GUID = &DynamicFieldGUID and version = &DynamicFieldVersion
…..
// Modify the value of the relevant data with the value of the field
Do Case
Case &FieldType = ‘date’
&WorkflowApplicationData.DateValue = CtoD(&FieldValue)
Case &FieldType = ‘numeric’
&WorkflowApplicationData.NumericValue = Val(&FieldValue)
Case &FieldType = ‘char’
&WorkflowApplicationData.CharacterValue = &FieldValue
// Other cases
…..
EndCase
COMMIT
EndFor