This example creates a custom property editor component named createContactActionEditor for an invocable action that uses a Contact object input parameter. An invocable action is an Apex method that you can add to your flow. In Flow Builder, an admin uses text fields to set the invocable action’s contact input parameter. When users run a flow for this example, the invocable action stores a new contact.
This Apex class file defines the createContact method that can run as an invocable action and its input variables. The @InvocableMethod annotation identifies the method that can run as an invocable action. The @InvocableVariable annotation identifies the variables used by the invocable method.
The invocable method registers the custom property editor component in the configurationEditor modifier. The component namespace is c unless the org has a custom namespace. If the org has a custom namespace, use that namespace to register the custom property editor component. For this example, the name of the component is c-create-contact-action-editor.
1//CreateContactAction.cls
2global class CreateContactAction {
3 global class CreateContactRequest {
4
5 @InvocableVariable
6 global Contact contact;
7 }
8
9 global class CreateContactResult {
10 @InvocableVariable
11 global Boolean isSuccess;
12
13 @InvocableVariable
14 global String errorMessage;
15
16 @InvocableVariable
17 global String contactId;
18 }
19
20 @InvocableMethod(label='Create Contact' configurationEditor='c-create-contact-action-editor')
21 global static List<CreateContactResult> createContact(List<CreateContactRequest> requests) {
22 List<CreateContactResult> results = new List<CreateContactResult>();
23 for(CreateContactRequest request : requests){
24 results.add(insertContact(request));
25 }
26 return results;
27 }
28
29 public static CreateContactResult insertContact(CreateContactRequest request) {
30 List<Contact> contactList = new List<Contact>();
31 contactList.add(request.contact);
32
33 Database.SaveResult[] srList = Database.insert(contactList, true);
34
35 CreateContactResult contactResult = new CreateContactResult();
36 for(Database.SaveResult sr: srList) {
37 if (sr.isSuccess()) {
38 contactResult.isSuccess = sr.isSuccess();
39 contactResult.contactId = sr.getId();
40 }
41 else {
42 for(Database.Error err : sr.getErrors()) {
43 contactResult.errorMessage = err.getStatusCode() + ': ' + err.getMessage();
44 }
45 }
46 }
47
48 return contactResult;
49 }
50}
Here’s the configuration file for CreateContactAction.
1
2
3<?xml version="1.0" encoding="UTF-8"?>
4<ApexClass xmlns="urn:metadata.tooling.soap.sforce.com" fqn="CreateContactAction">
5 <apiVersion>53.0</apiVersion>
6 <status>Active</status>
7</ApexClass>
These HTML, CSS, JavaScript, and configuration files define the custom property editor component createContactActionEditor for the action.
The component’s HTML template defines the UI for the custom property editor in Flow Builder.
1
2
3<template>
4 <div class="slds-m-top_small">
5 <h2 class="slds-text-heading_medium slds-p-around_xx-small lgc-bg-inverse">
6 Contact Primary Information
7 </h2>
8
9 <lightning-input
10 label="First Name"
11 value={defaultContact.FirstName}
12 onchange={handleFirstNameChange}
13 >
14 </lightning-input>
15
16 <lightning-input
17 label="Last Name"
18 value={defaultContact.LastName}
19 onchange={handleLastNameChange}
20 >
21 </lightning-input>
22 </div>
23
24 <div class="slds-m-top_small">
25 <h2 class="slds-text-heading_medium slds-p-around_xx-small lgc-bg-inverse">Contact Source</h2>
26
27 <lightning-input
28 label="European Country Code"
29 value={defaultContact.European_Country_Code__c}
30 onchange={handleCountryCodeChange}
31 >
32 </lightning-input>
33 </div>
34</template>
This example shows the custom property editor UI.

When the custom property editor component is initialized, its JavaScript class receives a copy of the flow metadata from Flow Builder. When the admin changes a value in the custom property editor, the custom property editor component dispatches an event to propagate the change back to Flow Builder.
Use @api properties to capture data from flows. Use events to report changes to flows at run time.
1//createContactActionEditor.js
2
3import { LightningElement, api } from "lwc";
4
5export default class CreateContactActionEditor extends LightningElement {
6 @api
7 inputVariables;
8
9 defaultContact = {
10 attributes: {
11 type: "Contact",
12 },
13 European_Country_Code__c: "FRA",
14 };
15
16 get contact() {
17 const param = this.inputVariables.find(({ name }) => name === "contact");
18 return param && param.value;
19 }
20
21 handleFirstNameChange(event) {
22 this.defaultContact["FirstName"] = event.detail.value;
23 this.handleContact();
24 }
25
26 handleLastNameChange(event) {
27 this.defaultContact["LastName"] = event.detail.value;
28 this.handleContact();
29 }
30
31 handleCountryCodeChange(event) {
32 this.defaultContact["European_Country_Code__c"] = event.detail.value;
33 this.handleContact();
34 }
35
36 handleContact() {
37 const newValue = JSON.stringify(this.defaultContact);
38 const valueChangedEvent = new CustomEvent("configuration_editor_input_value_changed", {
39 bubbles: true,
40 cancelable: false,
41 composed: true,
42 detail: {
43 name: "contact",
44 newValue,
45 newValueDataType: "SObject",
46 },
47 });
48 this.dispatchEvent(valueChangedEvent);
49 }
50}
Flow Builder has a JavaScript interface for communicating with a custom property editor. This JavaScript class uses the inputVariables interface.
When the custom property editor is initialized, inputVariables receives the value of the input variable in the invocable action from Flow Builder. The default values are set for type and European_Country_Code__c. When you use a literal value for an input that’s an sObject data type, specify the type value such as Contact.
The inputVariables data structure includes the name, value, and data type for each input variable.
1[{
2 name: 'contact',
3 value: '{
4 "attributes": {
5 "type": "Contact"
6 },
7 "FirstName" : "",
8 "LastName": "",
9 "European_Country_Code__c" : "FRA"
10 }',
11 valueDataType: 'SObject'
12}]
The get contact() method gets the value for the input variable for use in the custom property editor.
When an admin enters a value for an input in the custom property editor, the handleContact method dispatches a configuration_editor_input_value_changed event to Flow Builder. Flow Builder receives the event and updates the value in the flow.
Here’s the configuration file for createContactActionEditor.
1
2<?xml version="1.0" encoding="UTF-8"?>
3<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
4 <apiVersion>53.0</apiVersion>
5
6 <isExposed>true</isExposed>
7</LightningComponentBundle>