Adding Lightning Web Components to Flow Screens

For the last two years, Flow creators have been able to add lightning component to Flow Screens. This has powerfully extended the capability of screens. We’ve had a great time creating reusable components as a community, and many of those components are available for use to all parties.

The underlying web technology enabling these components, known as Aura, has served Salesforce well, but it’s more than 5 years old, and that’s a long time when it comes to changes in web technology. Salesforce recently released a major upgrade to its web technology called Lightning Web Components, and it’s now possible to embed this new generation of components into Flow screens. Let’s take a look at how it’s done.

In this demonstration, we create an LWC that allows the user to manually add and manage sharing settings on a record. This allows a Sharing button to be placed on Lightning record pages. The guts of this component consist of code written by resident Salesforce evangelist Shane McLaughlin.

To get an LWC to appear in Flow’s Screen Builder, you add a ‘lightning_FlowScreen’ target to the component’s meta file:

Attributes and Properties

To expose attributes from the LWC, you first use @api in the LWC’s javascript, as is standard for any property you want to make accessible outside of the component:

Then you additionally specify which of these public properties should be made visible in Flow by adding a targetConfig section:

The type field supports the same types that Flow supports with aura components. That includes specific Sobjects like “Contact” and specific SObject collections like “Account[]”. You can also use this interface to directly publish access to your apex class data structures for declarative manipulation in Flow . This extremely powerful technology is discussed at length here.

Note the following syntax for specifying SObjects and Apex Classes:

  • @salesforce/schema/<name of sObject>
  • apex://<name of Apex class>

Add array notation if it is a collection:  []

As of Summer ’20, you can now use generic SObjects. Here’s an example:

<targetConfig targets="lightning__FlowScreen">
    <propertyType name="T" extends="SObject" label="Object API Name" description="Select the api name of the SObject this component is going to be looking for" />

    <property name="selectedRecord" type="{T}" label="The selected Record" role="outputOnly" description="The SObject the user has selected" />
</targetConfig>
<targetConfig targets="lightning__FlowScreen">
    <propertyType name="T" extends="SObject" label="Object API Name" description="Select the api name of the SObject this component is going to be looking for" />

    <property name="selectedRecord" type="{T}" label="The selected Record" role="outputOnly" description="The SObject the user has selected" />
</targetConfig>

See this post for more detail.

Namespaces

With a namespaced org you have to include the namespace in the type string using the namespace prefix. So, for SObjects it would look like type=”@salesforce/schema/myNs__CoolCustomObject__c”. For apex types:”apex://myNs__MyApexClass”

Input and Output Control via Roles

The ‘role’ parameter can be added to property elements inside of targetConfigs. It has been created specifically to provide support for Flow’s ability to limit access to inputOnly or outputOnly. If no role is specified, the property is available in both directions.

Troubleshooting
If you hit this error: unable to find field dataType for complex reference: foo, you may need to set a default value on your attribute. For example, this error will occur if the value attribute is not set to an empty string here:

Example: Creating Contacts in Javascript and Passing Them to Flow

The component Contacter exposes two attributes. One is a Contact and the other is a collection of Contacts:

In the Flow, the outputs from these attributes are mapped manually to corresponding Flow resources:

Here’s an example of the corresponding javascript that creates new contacts and assigns them to the public attributes where Flow can get them:

Considerations When Working With Targets

Be Careful about Mixing Your Targets

The support mentioned above for SObjects and Apex Classes works only for Flow and not for other targets like lightning__RecordPage. So something like this will fail:

This can be hard to debug because each target has its own validation and the errors reported back don’t specify which target is the source of the difficulty. So you can get into a situation where you think your new Flow interface is complaining when it’s actually a problem being reported by App Builder.

Each property has to meet the requirements of each Target that mentions it.

Example: App Builder (and thus lightning__RecordPage, lightning__AppPage, lightning__HomePage) requires that if you add a ‘required’ attribute you also have to add a ‘default’ attribute. Flow does not have this requirement. If you try to add the same attribute to both sections, you’ll have to satisfy the combination of their constraints.

A good practice is to separate the App Builder targets from the Flow target, like this:

This helps but does not eliminate all possible interaction headaches. In the example above, Flow is forced to add a default attribute to editTabName because editTabName is also used in the AppBuilder targets, where that required/default issue is enforced. But it makes it easier to debug because you can comment out one set and see which validation is causing problems.

Events and Notification

Unlike Aura, the parent component doesn’t automatically learn when something changes in the child component. This takes some getting used to for old Aura hands.

There are two scenarios where this matters. For all of your LWC’s, think of the Flow Runtime as the parent container that needs to be notified about changes that need to be available external to your component. Any attribute that you intend to be used downstream in the Flow must be constantly reported to the Flow Runtime whenever the value changes in your component. (Likewise, if you have an lwc with lwc child components, you’ll have similar issues).

To notify Flow of changes in the value of an attribute in your component, the component must fire the FlowAttributeChangeEvent event.

In the following example, a ToDo LWC dispatches a FlowAttributeChangeEvent when a new item is added to the list of To Do’s:

import { LightningElement, api, track } from 'lwc';
import { FlowAttributeChangeEvent, FlowNavigationNextEvent } from 'lightning/flowSupport';
export default class Todos extends LightningElement {
    @api
    availableActions = [];
    @api
    get todos() {
        return this._todos;
    }
    set todos(todos = []) {
        this._todos = todos;
    }
    @track _todos = [];
    get hasTodos() {
        return this._todos && this._todos.length > 0;
    }
    handleUpdatedText(event) {
        this._text = event.detail.value;
    }
    handleAddTodo() {
        this._todos.push(this._text);
        // notify the flow of the new todo list
        const attributeChangeEvent = new FlowAttributeChangeEvent('todos', this._todos);
        this.dispatchEvent(attributeChangeEvent);
    }
    handleGoNext() {
        // check if NEXT is allowed on this screen
        if (this.availableActions.find(action => action === 'NEXT')) {
            // navigate to the next screen
            const navigateNextEvent = new FlowNavigationNextEvent();
            this.dispatchEvent(navigateNextEvent);
        }
    }
}

See additional pieces of the To Do example

Validation

To provide custom validation, create a function called “validate” in your js file:

@api
validate() {
    if(/* true conditions */) { 
         return { isValid: true }; 
        } 
    else { 
    //If the component is invalid, return the isValid parameter as false and return an error message. 
         return { 
               isValid: false, 
               errorMessage: '/*A message that helps your user enter a valid value or explains what went wrong.*/' 
                }; 
     } 
}

Reference Documentation

Navigation

To programmatically transition a Flow with an LWC component, you dispatch an event using this syntax:

import { LightningElement, api } from 'lwc';
import { FlowNavigationNextEvent } from 'lightning/flowSupport';

export default class NameOfYourComponent extends LightningElement {

   @api
   handleGoNext() {
       const nextNavigationEvent = new FlowNavigationNextEvent();
       this.dispatchEvent(nextNavigationEvent);
   }
}

The supported events are:

  • FlowNavigationNextEvent
  • FlowNavigationBackEvent
  • FlowNavigationFinishEvent
  • FlowNavigationPauseEvent

Data Sources

Attributes that use data sources will not show up in Flow Builder as mappable inputs or outputs. The simplest thing to do here is just assume that Flow doesn’t work with datasource properties yet. However, the attribute will function properly. So for example, you could use an attribute with a datasource to populate a picklist. But you could not directly pass in a default value for that picklist. You’d have to do it indirectly, passing in the value to an attribute that Flow can see and then copying it once you’re in your code.

Wire Service Considerations

It can be a little tricky to get wire services interacting properly with incoming flow data. Details here.

Examples

Set Sharing Manually

Sample Gists

https://gist.github.com/alexed1/e3e580103375120ca2dc1374bb4f73ff

Subscribe
Notify of
guest
18 Comments
Inline Feedbacks
View all comments
Chris V

Any chance you can elaborate on the validation portion? Im an Admin, not a Dev but I was able to build a good selection of LWC but still cannot get required to work like I did in my aura components.

Chris V

Good news! Adding @api made the validate method work! I have isRequired working now. Next I need to get min and max values working. import { LightningElement, track, api } from “lwc”; export default class Input extends LightningElement { @api value = “”; @api initials = “”; @api label = “”; @api compId = “”; @api min = “”; @api max = “”; @api isRequired = false; @track length = 0; @api handleChange(event) { this.value = event.target.value; this.length = this.value.length; } @api validate() { if (this.isRequired === false || this.length >= 1) { return { isValid: true }; // eslint-disable-next-line… Read more »

ivelin ganev

Hello guys, i have a question.
Aura property –
LWC property –

Please can you help me, why LWC property always give me “You specified an invalid type for” that response?
How can i get a collection of the Flow Action “get records” and pass it to the Javascript?

ivelin ganev

Thank you for the response.
My property looks like ( property name=”allContacts” type=”Contact[]” ).
Now i tried with ( property name=”allContacts” type=”@salesforce/schema/Contact[]” ) but the response was “You specified an invalid type for ‘allContacts'”

Ivelin Ganev

Hello everyone! Can you tell me can I still use aura:attribute name=”selectedRows” type=”SObject[]” but with the new syntax of LWC? I mean I would receive random sObject and want to handle it.

Many thanks!

Jens Becker

Hi Alex,

Are you aware, if we can use custom metadata type arrays for input properties? I tried

Which I can deploy, however, the input possibility in the flow disappears. So I assume, this works for APEX defined and “real” sObjects only.
Am I correct?

Thanks,

Jens

Gordon Vaynapel

Has anyone tried a @wire(getRecord, { recordId: ‘$recordId’, FIELDS }) with this? I cant seem to get anything back no errors no data.

Cassidy Rush

Hi Gordon, I’ve been having this same issue. Did you ever get getRecord to work in a flow?

Jonny Power

Anyone managed to get a callout or async/await process to work with the validate callback?

Thomas

Has anyone run into an issue of defining a property in the XML of a custom class with a namespace.

But I keep getting is either not supported by ‘lightning__FlowScreen’ or does not exist. when i deploy

Scott

The LWC Dev Guide suggests that the FlowAttributeChangeEvent should allow us to trigger component visibility logic in a flow screen but having trouble getting other components to show/hide based out outputs of a custom component. Am I reading the docs wrong? Has anyone else been able to get that to work?

[…] described here, you can insert lightning web components in Flow screens. If you’re using the LWC wire […]

[…] More information on adding LWC’s to Flow Screens […]

Srini

Hi..

I am trying to pass picklist value in flow to the LWC component which are both in the same screen….but I couldn’t receive the value…getting that api varible as undefined

Vinay

Brother..Did you find any solution or workaround to pass value from Flow to LWC?? If Yes pls let me know.

Thanks
Vinay
vinaytalanki@gmail.com

Vinay

How can I pass list of Sobject records from flow to LWC?