Skip to main content

Your First Steps with LWC Recipes

This guide will help you explore the Lightning Web Components Recipes app and understand how to use the examples to build your own components.
Before starting, make sure you’ve completed the Installation and have the LWC Recipes app running in your Salesforce org.

Exploring the App

1

Launch LWC Recipes

  1. Open your Salesforce org
  2. Click the App Launcher (waffle icon)
  3. Select LWC or LWC Recipes from the app list
You’ll see the main navigation with recipe categories on the left.
2

Browse recipe categories

The recipes are organized into logical categories:
  • Hello - Basic concepts and property binding
  • Composition - Component composition and iteration
  • Event Handling - Component events and communication
  • Data Access - Apex integration and data management
  • Lightning Data Service - Working with LDS and UI API
  • Navigation - Navigate to records, pages, and lists
  • Third-Party Libraries - Integrate external JavaScript libraries
3

View component source code

Each recipe includes a View Source button that links directly to the code on GitHub. Use this to see the complete implementation.

Understanding the Code Structure

Each Lightning Web Component consists of at least three files:
// JavaScript file - Component logic
import { LightningElement } from 'lwc';

export default class Hello extends LightningElement {
    greeting = 'World';
}

Recipe #1: Hello World

Let’s start with the simplest example - property binding.

What It Does

The hello component demonstrates how to bind a JavaScript property to the HTML template using curly braces {}.

The Code

import { LightningElement } from 'lwc';

export default class Hello extends LightningElement {
    greeting = 'World';
}

Key Concepts

  • Property Declaration: greeting = 'World' defines a reactive property
  • Data Binding: {greeting} displays the property value in the template
  • Lightning Card: Uses the <lightning-card> base component for consistent styling

Recipe #2: Calling Apex Methods

One of the most common tasks is retrieving data from Salesforce using Apex.

Imperative Apex Call

The apexImperativeMethod component shows how to call Apex methods imperatively using async/await.
import { LightningElement } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

export default class ApexImperativeMethod extends LightningElement {
    contacts;
    error;

    async handleLoad() {
        try {
            this.contacts = await getContactList();
            this.error = undefined;
        } catch (error) {
            this.contacts = undefined;
            this.error = error;
        }
    }
}

Key Concepts

  • @salesforce/apex Import: Import Apex methods using the wire format
  • Async/Await: Modern JavaScript pattern for handling asynchronous operations
  • Error Handling: Always use try/catch to handle potential errors
  • @AuraEnabled: Required annotation for Apex methods called from LWC

Recipe #3: Using Wire Adapters

Wire adapters provide reactive data binding to Salesforce data and metadata.

Wire Adapter for UI API

The wireGetRecord component uses the @wire decorator to fetch record data.
import { LightningElement, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/User.Name';
import EMAIL_FIELD from '@salesforce/schema/User.Email';
import Id from '@salesforce/user/Id';

export default class WireGetRecord extends LightningElement {
    userId = Id;

    @wire(getRecord, {
        recordId: '$userId',
        fields: [NAME_FIELD],
        optionalFields: [EMAIL_FIELD]
    })
    record;

    get recordStr() {
        return this.record ? JSON.stringify(this.record.data, null, 2) : '';
    }
}

Key Concepts

  • @wire Decorator: Automatically invokes the wire adapter when parameters change
  • Reactive Parameters: Use $ prefix (e.g., $userId) for reactive properties
  • Schema Import: Import field references using @salesforce/schema
  • Current User: Access logged-in user ID with @salesforce/user/Id

Recipe #4: Component Events

Components communicate through custom events.

Simple Event Handling

The eventSimple component demonstrates basic event handling.
import { LightningElement } from 'lwc';

export default class EventSimple extends LightningElement {
    page = 1;

    handlePrevious() {
        if (this.page > 1) {
            this.page = this.page - 1;
        }
    }

    handleNext() {
        this.page = this.page + 1;
    }
}

Key Concepts

  • Event Handlers: Use onclick={handlerName} to bind event handlers
  • Reactive Properties: Any property used in the template is reactive
  • Conditional Attributes: Dynamically disable buttons based on state

Recipe #5: Rendering Lists

Display collections of data using template for:each.

Iteration Example

The compositionIteration component shows how to render a list of contacts.
import { LightningElement } from 'lwc';

export default class CompositionIteration extends LightningElement {
    contacts = [
        {
            Id: '003171931112854375',
            Name: 'Amy Taylor',
            Title: 'VP of Engineering',
            Phone: '6172559632',
            Picture__c:
                'https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/amy_taylor.jpg'
        },
        {
            Id: '003192301009134555',
            Name: 'Michael Jones',
            Title: 'VP of Sales',
            Phone: '6172551122',
            Picture__c:
                'https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/michael_jones.jpg'
        },
        {
            Id: '003848991274589432',
            Name: 'Jennifer Wu',
            Title: 'CEO',
            Phone: '6172558877',
            Picture__c:
                'https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/jennifer_wu.jpg'
        }
    ];
}

Key Concepts

  • for:each Directive: Loop through arrays in templates
  • for:item: Defines the variable name for each iteration
  • key Attribute: Required for performance - use unique identifiers
  • Component Composition: Render child components in loops

Recipe #6: Lightning Data Service

Create records using Lightning Data Service UI API.

Creating Records

The ldsCreateRecord component demonstrates the createRecord API.
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { createRecord } from 'lightning/uiRecordApi';
import { reduceErrors } from 'c/ldsUtils';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import NAME_FIELD from '@salesforce/schema/Account.Name';

export default class LdsCreateRecord extends LightningElement {
    accountId;
    name = '';

    handleNameChange(event) {
        this.accountId = undefined;
        this.name = event.target.value;
    }

    async createAccount() {
        const fields = {};
        fields[NAME_FIELD.fieldApiName] = this.name;
        const recordInput = { apiName: ACCOUNT_OBJECT.objectApiName, fields };
        try {
            const account = await createRecord(recordInput);
            this.accountId = account.id;
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Account created',
                    variant: 'success'
                })
            );
        } catch (error) {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error creating record',
                    message: reduceErrors(error).join(', '),
                    variant: 'error'
                })
            );
        }
    }
}

Key Concepts

  • createRecord API: Create records without Apex
  • Schema Imports: Reference objects and fields safely
  • Toast Events: Display success/error messages to users
  • Error Handling: Use utility functions to format error messages

Recipe #7: Using Third-Party Libraries

Integrate JavaScript libraries like Chart.js for data visualization.

Chart.js Integration

The libsChartjs component shows how to load and use external libraries.
import { LightningElement } from 'lwc';
import chartjs from '@salesforce/resourceUrl/chartJs';
import { loadScript } from 'lightning/platformResourceLoader';

export default class LibsChartjs extends LightningElement {
    error;
    chart;
    chartjsInitialized = false;

    config = {
        type: 'doughnut',
        data: {
            datasets: [
                {
                    data: [30, 50, 20, 40, 60],
                    backgroundColor: [
                        'rgb(255, 99, 132)',
                        'rgb(255, 159, 64)',
                        'rgb(255, 205, 86)',
                        'rgb(75, 192, 192)',
                        'rgb(54, 162, 235)'
                    ],
                    label: 'Dataset 1'
                }
            ],
            labels: ['Red', 'Orange', 'Yellow', 'Green', 'Blue']
        },
        options: {
            responsive: false,
            plugins: {
                legend: {
                    position: 'right'
                }
            }
        }
    };

    async renderedCallback() {
        if (this.chartjsInitialized) {
            return;
        }
        this.chartjsInitialized = true;

        try {
            await loadScript(this, chartjs);
            const canvas = document.createElement('canvas');
            this.template.querySelector('div.chart').appendChild(canvas);
            const ctx = canvas.getContext('2d');
            this.chart = new window.Chart(ctx, this.config);
        } catch (error) {
            this.error = error;
        }
    }
}

Key Concepts

  • Static Resources: Upload libraries as static resources
  • loadScript API: Load external JavaScript files
  • renderedCallback: Lifecycle hook that runs after rendering
  • Initialization Flag: Prevent multiple library loads

Recipe #8: Navigation

Navigate to record pages programmatically. The navToRecord component uses the Navigation service.
import { LightningElement, wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import getSingleContact from '@salesforce/apex/ContactController.getSingleContact';

export default class NavToRecord extends NavigationMixin(LightningElement) {
    @wire(getSingleContact) contact;

    navigateToContact() {
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: this.contact.data.Id,
                objectApiName: 'Contact',
                actionName: 'view'
            }
        });
    }

    navigateToEdit() {
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: this.contact.data.Id,
                objectApiName: 'Contact',
                actionName: 'edit'
            }
        });
    }
}

Key Concepts

  • NavigationMixin: Extend your component with navigation capabilities
  • Page Reference: Define navigation targets with type and attributes
  • Standard Pages: Navigate to view, edit, or create record pages
  • Action Names: Use ‘view’, ‘edit’, or ‘new’ for different actions

Build Your First Component

Now that you’ve explored the recipes, try building your own component:
1

Create a new component

In VS Code with Salesforce extensions:
  1. Press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows)
  2. Select SFDX: Create Lightning Web Component
  3. Name your component (e.g., myFirstComponent)
2

Add component logic

Choose a recipe that matches your use case and adapt the code:
  • Need to fetch data? Start with apexImperativeMethod or wireGetRecord
  • Building a form? Look at ldsCreateRecord
  • Displaying a list? Check out compositionIteration
  • Need events? Explore eventSimple or eventWithData
3

Deploy and test

Deploy your component to your scratch org:
sf project deploy start
Then add it to a Lightning page using the Lightning App Builder.

Best Practices from the Recipes

Use Wire Adapters

Prefer @wire for data binding - it’s reactive and efficient

Handle Errors

Always use try/catch blocks and display user-friendly error messages

Import Schemas

Use @salesforce/schema imports for type-safe field references

Follow Naming Conventions

Use camelCase for properties and methods, PascalCase for component names

Learning Path

1

Week 1: Basics

  • Explore hello, clock, eventSimple
  • Learn property binding and event handling
  • Build a simple counter or calculator component
2

Week 2: Data Access

  • Study apexImperativeMethod, wireGetRecord
  • Understand wire adapters vs imperative calls
  • Create a component that displays Salesforce data
3

Week 3: Advanced Features

  • Dive into ldsCreateRecord, compositionIteration
  • Learn Lightning Data Service and component composition
  • Build a multi-component application
4

Week 4: Polish & Deploy

  • Explore libsChartjs, navToRecord
  • Add third-party libraries and navigation
  • Deploy your complete solution

Additional Resources

Complete Trailhead

Earn a badge while learning the recipes

LWC Dev Guide

Official Lightning Web Components documentation

Component Reference

Browse all base Lightning components

GitHub Issues

Ask questions and report issues
Pro Tip: Use the Code Tours feature in VS Code to get guided walkthroughs of complex recipes. Install the CodeTour extension to get started.

Build docs developers (and LLMs) love