# 539 Lwc Integration Guide C6e21df9

> Flow + LWC Integration Guide

- Skill: `tools-only/539-lwc-integration-guide-c6e21df9` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/539-lwc-integration-guide-c6e21df9`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/539-lwc-integration-guide-c6e21df9/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/539-lwc-integration-guide-c6e21df9

---

# Flow + LWC Integration Guide

This guide covers embedding custom Lightning Web Components in Flow Screens.

---

## Overview

```
┌─────────────────────────────────────────────────────────────────────┐
│                   FLOW SCREEN + LWC ARCHITECTURE                    │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │                      FLOW (Screen)                           │   │
│   │  ┌──────────────────────────────────────────────────────┐   │   │
│   │  │                  screens element                      │   │   │
│   │  │    ┌──────────────────────────────────────────────┐  │   │   │
│   │  │    │           fields > componentInstance         │  │   │   │
│   │  │    │                                              │  │   │   │
│   │  │    │   extensionName="c:myComponent"              │  │   │   │
│   │  │    │                                              │  │   │   │
│   │  │    │   inputParameters ────────────▶ @api (in)    │  │   │   │
│   │  │    │   outputParameters ◀────────── @api (out)    │  │   │   │
│   │  │    │                                              │  │   │   │
│   │  │    └──────────────────────────────────────────────┘  │   │   │
│   │  └──────────────────────────────────────────────────────┘   │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘
```

---

## Quick Reference

| Flow Element | LWC Requirement | Purpose |
|--------------|-----------------|---------|
| `extensionName` | `target="lightning__FlowScreen"` | Identify LWC component |
| `inputParameters` | `@api` with `role="inputOnly"` | Flow → LWC data |
| `outputParameters` | `@api` with `role="outputOnly"` | LWC → Flow data |
| N/A | `FlowAttributeChangeEvent` | LWC updates outputs |
| N/A | `FlowNavigationFinishEvent` | LWC controls navigation |

---

## Flow XML Structure

### Basic Screen with LWC

```xml
<screens>
    <name>My_LWC_Screen</name>
    <label>Custom Component Screen</label>
    <locationX>176</locationX>
    <locationY>158</locationY>
    <connector>
        <targetReference>Next_Element</targetReference>
    </connector>
    <showFooter>true</showFooter>
    <showHeader>true</showHeader>

    <fields>
        <name>myLwcField</name>
        <!-- Component reference: namespace:componentName -->
        <extensionName>c:myFlowComponent</extensionName>
        <fieldType>ComponentInstance</fieldType>

        <!-- Flow → LWC (inputs) -->
        <inputParameters>
            <name>recordId</name>
            <value>
                <elementReference>var_RecordId</elementReference>
            </value>
        </inputParameters>

        <!-- LWC → Flow (outputs) -->
        <outputParameters>
            <assignToReference>var_SelectedId</assignToReference>
            <name>selectedRecordId</name>
        </outputParameters>
    </fields>
</screens>
```

---

## Input Parameters

Pass data from Flow variables to LWC `@api` properties.

### Value Types

```xml
<!-- String literal -->
<inputParameters>
    <name>mode</name>
    <value>
        <stringValue>edit</stringValue>
    </value>
</inputParameters>

<!-- Boolean literal -->
<inputParameters>
    <name>showDetails</name>
    <value>
        <booleanValue>true</booleanValue>
    </value>
</inputParameters>

<!-- Number literal -->
<inputParameters>
    <name>maxRecords</name>
    <value>
        <numberValue>10</numberValue>
    </value>
</inputParameters>

<!-- Flow variable reference -->
<inputParameters>
    <name>recordId</name>
    <value>
        <elementReference>var_CurrentRecordId</elementReference>
    </value>
</inputParameters>

<!-- Record variable (SObject) -->
<inputParameters>
    <name>account</name>
    <value>
        <elementReference>get_Account</elementReference>
    </value>
</inputParameters>

<!-- Collection variable -->
<inputParameters>
    <name>selectedIds</name>
    <value>
        <elementReference>col_SelectedRecordIds</elementReference>
    </value>
</inputParameters>
```

### LWC Property Declaration

```javascript
// LWC must declare matching @api properties
@api recordId;      // Maps to inputParameter name="recordId"
@api mode;          // Maps to inputParameter name="mode"
@api showDetails;   // Maps to inputParameter name="showDetails"
@api maxRecords;    // Maps to inputParameter name="maxRecords"
```

---

## Output Parameters

Receive data from LWC `@api` properties into Flow variables.

### Flow XML

```xml
<!-- Simple value output -->
<outputParameters>
    <assignToReference>var_SelectedRecordId</assignToReference>
    <name>selectedRecordId</name>
</outputParameters>

<!-- Boolean output -->
<outputParameters>
    <assignToReference>var_IsComplete</assignToReference>
    <name>isComplete</name>
</outputParameters>

<!-- Collection output -->
<outputParameters>
    <assignToReference>col_SelectedIds</assignToReference>
    <name>selectedIds</name>
</outputParameters>
```

### LWC Dispatching Updates

**CRITICAL**: LWC must dispatch `FlowAttributeChangeEvent` for outputs to update.

```javascript
import { FlowAttributeChangeEvent } from 'lightning/flowSupport';

@api selectedRecordId;

handleSelection(event) {
    this.selectedRecordId = event.detail.id;

    // REQUIRED: Notify Flow of the change
    this.dispatchEvent(new FlowAttributeChangeEvent(
        'selectedRecordId',    // Property name (must match meta.xml)
        this.selectedRecordId  // New value
    ));
}
```

---

## Variable Types Mapping

| Flow Type | LWC Type | XML Declaration |
|-----------|----------|-----------------|
| `String` | `String` | `<dataType>String</dataType>` |
| `Number` | `Number` | `<dataType>Number</dataType>` |
| `Currency` | `Number` | `<dataType>Currency</dataType>` |
| `Boolean` | `Boolean` | `<dataType>Boolean</dataType>` |
| `Date` | `String` | `<dataType>Date</dataType>` |
| `DateTime` | `String` | `<dataType>DateTime</dataType>` |
| `Record` | `Object` | `<objectType>Account</objectType>` |
| `Collection` | `Array` | `<isCollection>true</isCollection>` |

### Variable Declaration Examples

```xml
<!-- String variable -->
<variables>
    <name>var_SelectedId</name>
    <dataType>String</dataType>
    <isCollection>false</isCollection>
    <isInput>false</isInput>
    <isOutput>false</isOutput>
</variables>

<!-- Boolean variable with default -->
<variables>
    <name>var_IsComplete</name>
    <dataType>Boolean</dataType>
    <isCollection>false</isCollection>
    <isInput>false</isInput>
    <isOutput>false</isOutput>
    <value>
        <booleanValue>false</booleanValue>
    </value>
</variables>

<!-- Collection of strings -->
<variables>
    <name>col_SelectedIds</name>
    <dataType>String</dataType>
    <isCollection>true</isCollection>
    <isInput>false</isInput>
    <isOutput>false</isOutput>
</variables>

<!-- Record variable -->
<variables>
    <name>var_Account</name>
    <dataType>SObject</dataType>
    <isCollection>false</isCollection>
    <isInput>false</isInput>
    <isOutput>false</isOutput>
    <objectType>Account</objectType>
</variables>
```

---

## Validation Patterns

### Check LWC Output Before Proceeding

```xml
<screens>
    <name>LWC_Screen</name>
    <!-- ... -->
    <connector>
        <targetReference>Validate_Output</targetReference>
    </connector>
</screens>

<decisions>
    <name>Validate_Output</name>
    <label>Validate LWC Output</label>
    <defaultConnector>
        <targetReference>Show_Error</targetReference>
    </defaultConnector>
    <defaultConnectorLabel>Invalid</defaultConnectorLabel>
    <rules>
        <name>Is_Valid</name>
        <conditionLogic>and</conditionLogic>
        <conditions>
            <leftValueReference>var_SelectedId</leftValueReference>
            <operator>IsNull</operator>
            <rightValue>
                <booleanValue>false</booleanValue>
            </rightValue>
        </conditions>
        <connector>
            <targetReference>Continue_Flow</targetReference>
        </connector>
        <label>Valid Selection</label>
    </rules>
</decisions>
```

### LWC-Side Validation

```javascript
@api validate() {
    // Flow calls this when user clicks Next
    if (!this.selectedRecordId) {
        return {
            isValid: false,
            errorMessage: 'Please select a record before continuing.'
        };
    }
    return { isValid: true };
}
```

---

## Screen Configuration

### Navigation Options

```xml
<screens>
    <name>My_Screen</name>
    <allowBack>true</allowBack>      <!-- Show Back button -->
    <allowFinish>true</allowFinish>  <!-- Allow Finish (last screen) -->
    <allowPause>true</allowPause>    <!-- Show Pause button -->
    <showFooter>true</showFooter>    <!-- Show button bar -->
    <showHeader>true</showHeader>    <!-- Show screen label -->
</screens>
```

### Hiding Standard Navigation

When LWC handles its own navigation:

```xml
<screens>
    <name>Custom_Nav_Screen</name>
    <showFooter>false</showFooter>  <!-- LWC provides buttons -->
    <!-- ... -->
</screens>
```

LWC then uses:
```javascript
import { FlowNavigationFinishEvent } from 'lightning/flowSupport';

handleNext() {
    this.dispatchEvent(new FlowNavigationFinishEvent('NEXT'));
}
```

---

## Multiple LWCs in One Screen

```xml
<screens>
    <name>Multi_LWC_Screen</name>
    <label>Multiple Components</label>

    <!-- First LWC -->
    <fields>
        <name>headerComponent</name>
        <extensionName>c:flowHeader</extensionName>
        <fieldType>ComponentInstance</fieldType>
        <inputParameters>
            <name>title</name>
            <value><stringValue>Select Options</stringValue></value>
        </inputParameters>
    </fields>

    <!-- Standard Flow field between LWCs -->
    <fields>
        <name>instructions</name>
        <fieldText>&lt;p&gt;Choose from the options below&lt;/p&gt;</fieldText>
        <fieldType>DisplayText</fieldType>
    </fields>

    <!-- Second LWC -->
    <fields>
        <name>selectorComponent</name>
        <extensionName>c:recordSelector</extensionName>
        <fieldType>ComponentInstance</fieldType>
        <outputParameters>
            <assignToReference>var_SelectedId</assignToReference>
            <name>selectedId</name>
        </outputParameters>
    </fields>
</screens>
```

---

## Error Handling

### Capture LWC Error Output

```xml
<fields>
    <outputParameters>
        <assignToReference>var_ErrorMessage</assignToReference>
        <name>errorMessage</name>
    </outputParameters>
</fields>

<!-- Check for errors after screen -->
<decisions>
    <name>Check_Errors</name>
    <rules>
        <name>Has_Error</name>
        <conditions>
            <leftValueReference>var_ErrorMessage</leftValueReference>
            <operator>IsNull</operator>
            <rightValue>
                <booleanValue>false</booleanValue>
            </rightValue>
        </conditions>
        <connector>
            <targetReference>Error_Handler</targetReference>
        </connector>
    </rules>
</decisions>
```

### LWC Dispatching Errors

```javascript
handleError(error) {
    this.errorMessage = this.reduceErrors(error);
    this.dispatchEvent(new FlowAttributeChangeEvent(
        'errorMessage',
        this.errorMessage
    ));
}
```

---

## Context Variables

Pass Flow context to LWC using record context:

```xml
<!-- In Flow: Map $Record context -->
<inputParameters>
    <name>recordId</name>
    <value>
        <elementReference>$Record.Id</elementReference>
    </value>
</inputParameters>
<inputParameters>
    <name>objectApiName</name>
    <value>
        <elementReference>$Record.Object</elementReference>
    </value>
</inputParameters>
```

---

## Templates

| Template | Use Case |
|----------|----------|
| `templates/screen-flow-with-lwc.xml` | Complete LWC screen integration |
| `templates/apex-action-template.xml` | Calling Apex from Flow |

---

## Cross-Skill Integration

| Integration | See Also |
|-------------|----------|
| LWC Component Setup | [sf-lwc/docs/flow-integration-guide.md](../../sf-lwc/docs/flow-integration-guide.md) |
| Full Triangle Architecture | [triangle-pattern.md](triangle-pattern.md) |
| LWC FlowAttributeChangeEvent | [sf-lwc/templates/flow-screen-component/](../../sf-lwc/templates/flow-screen-component/) |

---

## Troubleshooting

| Issue | Cause | Solution |
|-------|-------|----------|
| LWC not appearing in Flow Builder | Missing `isExposed` or target | Add `isExposed=true` and `target="lightning__FlowScreen"` |
| Properties not showing in builder | Missing `targetConfigs` | Add `targetConfig` with property definitions |
| Outputs not updating | Missing FlowAttributeChangeEvent | Dispatch event when value changes |
| Type mismatch error | Wrong dataType | Match Flow variable type to LWC property type |
| LWC not receiving inputs | Property name mismatch | Ensure `name` matches `@api` property exactly |
| Navigation not working | Wrong event type | Use `FlowNavigationFinishEvent` with action string |

