Rendering Form Data in Workflow Rule Services
Rendering Form Data in Workflow Rule Services
Standard Web Central edit forms use a system workflow rule service ( AbCommonResources-getDataRecord ) to retrieve data records that they display. You can override this service for a specific form if the data should be “massaged” before displaying in the form. For example, if the data record contains an XML field, you might want to display separate XML attributes as form fields. In this case, you can use a custom workflow rule service to extract XML attribute values and send them to the form as if they were “real” fields.
The simplest way to implement such service is to delegate the bulk of data retrieval to the standard service, and then change the response values before returning them to the form. This code pattern is shown below:
public void getWorkflowRuleRecord(EventHandlerContext context)
{
//
get data records using the default service
ViewHandlers
defaultService = new ViewHandlers();
defaultService.getDataRecord(context);
//
get JSON data prepared by the default service
JSONObject
data = context.getJSONObject("jsonExpression");
//
add or change the data values
...custom
code goes here...
//
put the updated JSON data back into the response
context.addResponseParameter("jsonExpression",
data.toString());
}
In the example below, the service extract the “ xml_rule_props\@description ” XML attribute and copies it as “ afm_wf_rules.description ” field into the data record:
// custom code goes here
JSONArray records
= data.getJSONArray(ViewHandlers.OUTPUT_RECORDS);
// check that there is
a record
if (records.length()
> 0) {
JSONObject
record = records.getJSONObject(0);
//
parse afm_wf_rules.xml_rule_props field value into XML DOM
Element
xmlElement = getEventHandlerElement(context, record,
"afm_wf_rules.xml_rule_props",
"xml_rule_properties");
//
get the description
String
description = xmlElement.attributeValue("description");
//
copy into output record as a “field” value
record.put("afm_wf_rules.description",
description);
}
The form can use this workflow rule as follows:
<panel type="form"
id="wf_form" showOnLoad="false" columns="3"
refreshWorkflowRuleId="AbCommonResources-getWorkflowRuleRecord">
The description field can be added to the form using alias:
<field table="afm_wf_rules"
name="xml_rule_props" alias="afm_wf_rules.description">
<title
translatable="true">Description</title>
</field>
Note that even though the field displays “virtual” value, it should be based on a real field that roughly matches the type of the “virtual” field, in order to correctly format the displayed value. If this is not possible, then the view developer can use a custom UI field based on HTML and use JavaScript to display the value retrieved from the workflow rule.
Similar technique can be used to implement custom services that save form fields in non-standard fashion. The code skeleton is shown below:
public void saveWorkflowRuleRecord(EventHandlerContext
context) {
//
deserialize form input values from the WFR context
Map
fieldValues = fromJSONObject(
context.getJSONObject(ViewHandlers.INPUT_FIELD_VALUES));
Map
oldFieldValues = fromJSONObject(
context.getJSONObject(ViewHandlers.INPUT_OLD_FIELD_VALUES));
//
add, change or remove the data values
...custom
code goes here...
//
serialize updated values back into WFR context
context.addResponseParameter(ViewHandlers.INPUT_FIELD_VALUES,
toJSONObject(fieldValues));
context.addResponseParameter(ViewHandlers.INPUT_OLD_FIELD_VALUES,
toJSONObject(oldFieldValues));
//
call default service
ViewHandlers
defaultHandler = new ViewHandlers();
defaultHandler.saveDataRecord(context);
}
Drawing from our XML example, if the user changes the description, you would want to put it back into the XML field and then save the record using the standard service:
// obtain "virtual"
description value, and remove it from the map
//
because it cannot be saved that way
String
description = (String) fieldValues.remove("afm_wf_rules.description");
//
obtain xml_rule_props XML text
String
xml_rule_props = (String) oldFieldValues.get("afm_wf_rules.xml_rule_props");
//
if new record does not have XML properties yet
if
(xml_rule_props.length() == 0) {
//
create empty XML skeleton
xml_rule_props
=
"<xml_rule_properties><eventHandlers>"
+
"<eventHandler><inputs/></eventHandler>"
+
"</eventHandlers></xml_rule_properties>";
}
//
parse XML text into XML DOM
XmlImpl
xml = parseXmlString(context, xml_rule_props);
//
set the description attribute in XML DOM
xml.setAttribute(
"xml_rule_properties",
"description", description, true);
//
format XML DOM back into text
xml_rule_props
= formatXmlString(xml);
//
put the XML text into the record, overwriting old value
fieldValues.put("afm_wf_rules.xml_rule_props",
xml_rule_props);
//
remove "virtual" description value from the old values too
oldFieldValues.remove("afm_wf_rules.description");
The form can use this workflow rule as follows:
<panel type="form"
id="wf_form" showOnLoad="false" columns="3"
refreshWorkflowRuleId="AbCommonResources-getWorkflowRuleRecord"
saveWorkflowRuleId="AbCommonResources-saveWorkflowRuleRecord">
The form can also use custom workflow rules to obtain default values for the new record (Add New button), and to delete a data record from the database:
<panel type="form" id="wf_form" showOnLoad="false" columns="3" refreshWorkflowRuleId="AbCommonResources-getWorkflowRuleRecord" saveWorkflowRuleId="AbCommonResources-saveWorkflowRuleRecord" clearWorkflowRuleId="AbCommonResources-clearWorkflowRuleRecord" deleteWorkflowRuleId="AbCommonResources-deleteWorkflowRuleRecord">