# Custom Property Editor JavaScript Interface

A custom property editor uses these JavaScript functions to communicate with Flow Builder.

## `inputVariables`

The `inputVariables` interface provides data about the FlowScreenField metadata.

```javascript
_inputVariables = [];

@api
get inputVariables() {
    return this._inputVariables;
}

// Set a field with the data that was stored from the flow.
set inputVariables(variables) {
    this._inputVariables = variables || [];
}
```

The data structure in `_inputVariables` includes the name, value, and data type for each input variable.

```xml
[{
    name: 'volume',
    value: '10',
    valueDataType: 'Number'
}]
```

For more information about flow metadata, see [Flow Metadata API](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_visual_workflow.htm).

## `builderContext`

The `builderContext` interface provides data about elements and resources in the flow. For example, the `screens` and `actionCalls` data structures include the names and types of input variables. In Flow Builder, an admin can use the data about other elements and resources as inputs on the custom property editor for the screen component’s input attributes.

The data structure passed into the custom property editor from the `builderContext` interface includes the elements and resources in the flow.

```xml
{
    actionCalls: [],
    apexPluginCalls: [],
    constants: [],
    formulas: [],
    recordCreates: [],
    recordDeletes: [],
    recordLookups: [],
    recordUpdates: [],
    screens: [],
    stages: [],
    textTemplates: [],
    variables: []
}
```

For more information about flow metadata, see [Flow Metadata API](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_visual_workflow.htm).

In the following example, a developer creates a custom flow screen component and its custom property editor. In Flow Builder, an admin uses the combo box to set the sender’s name for an email. When users run the flow, the flow screen shows the selected name for the email.

The following HTML, JavaScript, and configuration file define the custom flow screen component.

```html
<!--htmlEmail.html-->
<template>
  <p>Selected sender's name is: {senderName}</p>
</template>
```

This JavaScript file defines a `senderName` public property.

```javascript
// htmlEmail.js

import { LightningElement, api } from "lwc";

export default class HTMLEmail extends LightningElement {
  @api senderName;
}
```

This configuration file registers the custom property editor.

```xml
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>49.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__FlowScreen</target>
    </targets>
    <masterLabel>HTMLEmail</masterLabel>
    <targetConfigs>
        <targetConfig targets="lightning__FlowScreen" configurationEditor="c-html-email-editor">
            <property name="senderName" type="String" role="inputOnly" />
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>
```

The following HTML, JavaScript, and configuration files define the custom property editor for the screen component.

This HTML file defines the UI for the custom property editor in Flow Builder. The UI shows a combo box Lightning base component.

```html
<!--htmlEmailEditor.html-->
<template>
  <div class="slds-p-around_xx-small">
    <lightning-combobox
      name="senderName"
      label="Sender Display Name"
      value={senderName}
      placeholder="Select Sender"
      options={options}
      onchange={handleChange}
    >
    </lightning-combobox>

    <p class="slds-p-top_xx-small">Selected sender's name is: {senderName}</p>
  </div>
</template>
```

The JavaScript class receives a copy of the flow metadata from Flow Builder when the custom property editor is initialized. If the admin makes an update in the custom property editor, an event is dispatched to propagate the change back to Flow Builder.

```javascript
// htmlEmailEditor.js
import { LightningElement, api } from "lwc";
export default class HtmlEmailEditor extends LightningElement {
  @api
  inputVariables;

  @api
  builderContext;

  get senderName() {
    const param = this.inputVariables.find(({ name }) => name === "senderName");
    return param && param.value;
  }

  get options() {
    const variables = this.builderContext.variables;
    return variables.map(({ name, value }) => ({
      label: name,
      value: value.stringValue,
    }));
  }

  handleChange(event) {
    if (event && event.detail) {
      const newValue = event.detail.value;
      const valueChangedEvent = new CustomEvent("configuration_editor_input_value_changed", {
        bubbles: true,
        cancelable: false,
        composed: true,
        detail: {
          name: "senderName",
          newValue,
          newValueDataType: "String",
        },
      });
      this.dispatchEvent(valueChangedEvent);
    }
  }
}
```

The `senderName` method returns information about the `senderName` input variable that was stored using the `inputVariables` interface. The `options` method returns a list of merge fields that was stored using the `builderContext` interface method. The custom property editor shows the merge fields as input values for the screen component’s input attributes.

![Custom property editor with a combo box](https://a.sfdcstatic.com/developer-website/sfdocs/lwc/media/flow_custom_property_editor_combobox.png)

## `elementInfo`

The `elementInfo` interface provides data about the custom flow screen component or custom action that is invoking the custom property editor. Use this interface to disambiguate different instances of a screen component or an action.

This example stores the flow metadata in `_elementInfo`, but you can name the field whatever you like.

```
_elementInfo = {};
@api
get elementInfo() {
    return this._elementInfo;
}

// Set a local variable with the data that was stored from flow.
set elementInfo(info) {
    this._elementInfo = info || {};
}
```

The data structure in `_elementInfo` includes the flow element’s API name and type from the flow metadata.

```xml
{
    apiName: 'slider',
    type: 'Screen'
}
```

Valid values for type are:

- `Screen`—A screen element
- `Action`—An action element

## `validate`

Use the `validate` interface to perform custom validation in the custom property editor. When a flow admin clicks **Done** in Flow Builder’s screen editor, Flow Builder evaluates the `validate` function in each custom property editor. If the function returns the `key` and `errorString` data structure, the screen editor shows the number of errors.

:::note
Flow Builder shows only the number of errors. Write code to show error strings in your custom property editor.
:::

This example stores the data in the `validity` field, but you can use any field name. To show error strings in the custom property editor, we use `sliderCmp` to query, set, and report the error string.

```javascript
@api
validate() {
    const sliderCmp = this.template.querySelector('lightning-slider');
    const validity = [];
    if (this.volume < 0 || this.volume > 100) {
        sliderCmp.setCustomValidity('The slider range is between 0 and     100.');
        validity.push({
            key: 'Slider Range',
            errorString: 'The slider range is between 0 and 100.',
        });
    } else {
        sliderCmp.setCustomValidity('');
    }
    sliderCmp.reportValidity();
    return validity;
}
```

## `genericTypeMappings`

The `genericTypeMappings` data structure includes the name and value for each input. The `typeName` is the name of the generic `sObject` input; for example, `‘T__param1’`. The `typeValue` is the specific value for the generic `sObject` input; for example, `Account`.

```xml
[{
    typeName: 'T__param1',
    typeValue: 'Account'
}]
```

## Event Types

To report input value changes to Flow Builder, dispatch events from the custom property editor’s `handleChange` function. Set `bubbles` and `composed` to true.

The valid values for event types are:

- `configuration_editor_input_value_changed`—An event type that dispatches when an input value changes.
- `configuration_editor_input_value_deleted`—An event type that dispatches when an input value is deleted.
- `configuration_editor_generic_type_mapping_changed`—An event type that dispatches when a generic `sObject` input value changes.

These `detail` properties define the input for reporting changes.

- `name`—The input variable in the screen component’s JavaScript class.
- `newValue`—The new value of the input.
- `newValueDataType`—The new data type of the input.
- `typeName`—The generic `sObject` input in the screen component’s JavaScript class or invocable method’s Apex class. To reference the `typeName` in the custom property editor for a screen component, reference the `propertyType` subtag’s `name` attribute. The value must be inside curly braces for example `property type="{T}"`. To define the property as a generic `sObject` collection data type, append `[]`, for example `property type="{T[]}"`. To reference the `typeName` in the custom property editor for an invocable action, prepend `T__` to input names and `U__` to output names for example `T__param1`.
- `typeValue`—The specific value for the generic `sObject` input or output.

For example, when an admin enters a value for `volume` in the custom property editor, it dispatches an event. Flow Builder receives the event and updates the value in the flow.

```javascript
handleChange(event) {
    if (event && event.detail) {
        const newValue = event.detail.value;
        const valueChangedEvent = new CustomEvent(
            'configuration_editor_input_value_changed', {
            bubbles: true,
            cancelable: false,
            composed: true,
            detail: {
                name: 'volume',
                newValue,
                newValueDataType: 'Number'
            }
            }
        );
        this.dispatchEvent(valueChangedEvent);
    }
}
```

When a value is removed from the input, dispatch a custom `configuration_editor_input_value_deleted` event.

```javascript
handleDelete(event) {
  if (event) {
    const valueDeletedEvent = new CustomEvent('configuration_editor_input_value_deleted', {
        bubbles: true,
        cancelable: false,
        composed: true,
        detail: {
            name: 'volume'
        }
    });
    this.dispatchEvent(valueDeletedEvent);
  }
}
```

**See Also**

- [Create and Dispatch Events](/docs/platform/lwc/guide/events-create-dispatch.md)
