Custom Property Editors – Prerelease Documentation

Introduction

9/20 Update: Official documentation is now available here.

This documentation refers to the Summer ’20 release of Custom Property Editors.
To see the original pilot documentation for Spring ‘20, click here. Note that there are significant differences, and we strongly recommend not working with Spring ’20 for this.

image.png

NEW! Walkthrough Video for Developers (WARNING: this shows the Pilot syntax, which has changed for Summer ‘20. See above)
Presentation Introduction
Pilot community

Register a Custom Property Editor with an Invocable Action

Use the new property “configurationEditor” on the “@InvocableMethod” annotation to provide a component reference. Don’t forget the ‘c:’!

  • An Apex class can have only one method marked with the @InvocableMethod annotation.
  • A user can invoke an invocable action either via Flow Builder or by calling Salesforce APIs.
// Example of an invocable action associating an LWC component
class CPEDemo {
@InvocableMethod(configurationEditor = 'c:cpeDemo')
global static List<Contact> invocableMethod(/*input parameters*/) {
// does something
}
}

For more information on Invocable Actions, see this. Additional community resources are available here.

Register a Custom Property Editor with a Lightning Web Component

Add a configurationEditor attribute to the TargetConfig element associated with the target ‘lightning__FlowScreen“. The configuration editor is the CPE you’re building and the targetConfig you modify is in the meta xml file of the underlying Flow screen component. Note that the name of the component has to be specified using lwc notation (hyphens and not colons).

image.png

This example shows a namespace called ’ns’ being used as part of the configuration:

<targetConfigs>
<targetConfig targets="lightning__FlowScreen" configurationEditor="ns-my-component" category="Input">
<!-- input only, will be part of CPE -->
<property name="prop1" type="String" role="inputOnly"/>

<!-- output only, wont be included in CPE -->
<property name="prop2" type="String" role="outputOnly"/>

<!-- Can be both input or output, will be part of CPE -->
<property name="prop3" type="String"/>

</targetConfig>
</targetConfigs>

Note that, similar to Flow Actions, you can’t yet use a custom property editor with an LWC that uses the Summer ’20 dynamic sobject attributes.

Setup

1) Select an existing Invocable Action
In our example, we’ll create a Custom Property Editor (“CPE“) for the Send Rich Email invocable action. Here’s the original version of the code.

2) Create a new LWC to form the CPE for your Invocable Action.
Working in the same sfdx project that contains my invocable action, we create an lwc called sendRichEmailCPE:

image.png

3) Register the new CPE with its Invocable Action
To bind our nascent CPE to its Action, we add the property to the @invocableMethod annotation:

image.png

From here, you can add components to your Lightning Web Component. Don’t forget to dispatch change events.


Reference

builderContext Attribute

The primary goal of property editors in flow is to facilitate mapping of upstream data to downstream data. In the baseline property editor, each field is a combo box that pops up to reveal a list of all of the available resources. The resources can be thought of as merge fields, or references to data.

In a standard Flow property editor, merge fields are shown and selected via a Flow-optimized combo box:

image.png

To make it possible for your Custom Property Editor to provide a similar mapping capability, Flow Builder will provide you with a builderContext object when it initializes your CPE. This object’s schema is a subset of, and in the same format, as the Flow metadata.

Here’s an example of some of the builderContext:

image.png

To use builder context, expose a builderContext attribute on your CPE, either directly:


@api builderContext;

or by using getters and setters:

 @api get builderContext() {
return this._builderContext;
}

set builderContext(value) {
this._builderContext = value;
}

BuilderContext only flows in one direction – into the Custom Property Editor. As the user configures the editor by inputting information, that information gets handled by the inputVariables attribute, which we’ll talk about next.

inputVariables Attribute

The inputVariables property tracks the actual values that users are entering in your custom property editors. When you initialize your CPE, Flow Builder will inspect the metadata of the current Flow and provide in the inputVariables object any values already stored in the metadata.

The inputVariables data represents the underlying information stored in the action’s FlowActionCallInputParameter list.

The format is:

[
{"id":"orgWideEmailAddressId","value":"skdjfsdf","dataType":"String"},
{"id":"replyEmailAddress","value":"curInputString1","dataType":"reference"}
]

See “Notifying Flow Builder of Value Changes”, below, for information about literals and references.

elementInfo Attribute

If you add the @api attribute elementInfo, Flow Builder will pass information about the element that the custom property editor is part of. The form of this data structure is:

{apiName: 'CreateATask', // dev name of the action or screentype: 'Action', // or 'Screen'}

This can be useful if the flow has multiple instances of a particular action, and the CPE wants to know which one it’s being invoked by. In some cases, the CPE might want to pass this information to a server process.

Validate Function

When a Flow is saved, if it has any elements that use custom property editors, it will look for the presence of a validate method. if it finds one, it will call it. This gives your CPE the opportunity to block the save and report errors. If you return the data structure shown below, Flow will stop the save.

  //return the data structure shown below which is an array of objects

// for example, if the error is due to a slider being out of bounds then you
//could return this data structure:
[{
key: 'SendRichEmail - Set Return Date Maximum',
errorString: 'Return Date Maximum must be less than 30'
}]

Note that although this interface allows the specific error strings to be returned to Flow Builder, Flow Builder does not currently have a way to display them to users, although it will show the number of errors. In a future release, Flow Builder will have a mechanism to pass error strings through to a visible, global display. Therefore, make sure that you visibly surface all error strings in your own custom property editor.

Notifying Flow Builder of Value Changes

In the LWC framework, containers do not automatically find out about value changes in attributes of their children. The burden is on you to dispatch events to report those changes.

There are two types of value change events: ‘configuration_editor_input_value_changed’ and ‘configuration_editor_input_value_deleted’ (Deleted is a separate event because there’s no way to pass a null value reliably with a single value change event)

Changing a Value

The structure for a configuration_editor_input_value_changed notification is:

dispatchFlowValueChangeEvent(id = '', newValue = '', newValueDataType = '') {
const valueChangedEvent = new CustomEvent('configuration_editor_input_value_changed', {
bubbles: true,
cancelable: false,
composed: true,
detail: {
id: id,
newValue: newValue,
newValueDataType: newValueDataType
}
});
this.dispatchEvent(valueChangedEvent);
}
parameternotesCD
idpass the name of the attribute that has changed
newValuethe new value. If you are mapping in a variable/reference, you currently need to specify it in the syntax used by Flow Builder “{!myVar1}”. Whenever you use a variable for this parameter, make sure the accompanying newValueDataType is “reference”
newValueDataTypethe type of the value. supported values: “string”, “number”, “boolean”, “reference”.

Setting the newValue
If you are passing a reference, you must include the braces and exclamation point, like this:

this.dispatchFlowValueChangeEvent(elementName, '{!Get_Contacts}','reference');  //how to pass a mergefield

If you are passing a literal, do not use braces:

this.dispatchFlowValueChangeEvent(elementName, 'LaDeeDa','String' ); how to pass a literal

Setting the newValueDataType
Determine whether you are passing a reference (mergefield) or a literal string. Basically, if the value for a field matches an existing variable in builderContext, treat it as a reference.

The supported values for newValueDataType correspond to the types available for Flow Variables:

typeBCD
referencecorresponds to the Record data type for Flow Variables. Use this for both single records and collections. Note the lower-casing.
String
Number
Boolean
Currency
ApexCorresponds to Apex-defined data types. This is extremely powerful when it comes to transmitting rich, nested data between your custom property editor and your underlying invocable action
DateTime
Date

‘Bubbles’ and ‘Composed’
Both of these must be set to true to allow the dispatched events to reach Flow Builder. Note that this overrides the general guidance on events that Salesforce provides here.

configuration_editor_input_value_deleted is only needed when you want to ‘turn off’ an attribute. The behavior is similar to toggling off an attribute in the traditional action property editor. Note that the only thing needed in the payload is the name of the attribute.

Deleting an Existing Value

dispatchValueDeleteEvent(id = '') {
const valueDeletedEvent = new CustomEvent('configuration_editor_input_value_deleted', {
bubbles: true,
cancelable: false,
composed: true,
detail: {
id: id
}
});
this.dispatchEvent(valueDeletedEvent);
}

APPENDIX

repo with sample code: https://github.com/alexed1/CustomPropertyEditors



Here’s source code for the best CPE sample code, currently: https://github.com/alexed1/LightningFlowComponents/tree/master/flow_action_components/SendRichEmailCPE