Salesforce Interview Questions & Answers Book is now available!

Grab Now

LWC course

Learn Lightning Web Components (LWC): A Hands-On Course from Basics to Real Projects

Learn Lightning Web Components hands-on: templates, getters, events, wire adapters, Lightning Data Service, Apex and Lightning Message Service, built live in a real org.

By Teja, ex-Salesforce engineer · Updated October 6, 2026 · 5 min read

TL;DR

  • Lightning Web Components is Salesforce's standards-based UI framework and the default for all new Lightning Experience UI. It's modern JavaScript plus decorators, wire adapters and base components.
  • Learn it in this order: JavaScript (free course), then the LWC course for events, Lightning Data Service, Apex and messaging, then real projects to tie it together.
  • LWC templates can't contain expressions. Compute everything in JavaScript getters. Getting that habit early prevents a whole class of bugs.

What the courses cover

Pulled live from the course catalogue — module by module.

Lightning Web Components Development58 episodes · 7.9 hours
  • Introduction
  • Events
  • Lightning Data Services
  • LWC & Apex
  • Configuring & Exposing Web Components
  • Navigation in LWC
  • Coding Challenges
  • Lightning Message Service
  • Lightning Testing Service
Javascript for Lightning Web Components [FREE]22 episodes · 2.6 hours · free
Build Real Projects with Lightning21 episodes · 3.5 hours
  • URL Shortener App
  • Coding Reddit.com clone with Lightning Framework
  • File Uploader
  • Hacking DataTable Component

To learn Lightning Web Components, get comfortable with modern JavaScript first, then learn how a component's template binds to its class, how components talk through events, how to read and write data with Lightning Data Service and Apex, and how to expose components to Lightning pages. The courses above follow that order, from the free JavaScript course to a Reddit clone and a URL shortener in the real-projects course. Every component is built live in a real org, errors included.

What LWC is and where you use it

Lightning Web Components is Salesforce's UI framework, built on web standards: custom elements, ES modules and the shadow DOM. Each component is a folder with an HTML template, a JavaScript class and a metadata file that says where the component can be used.

On real projects, I build LWCs for:

  • Record page components that show related data in a more useful shape than a related list
  • Screen flow components that give flows a custom input or display
  • Quick actions for focused tasks launched from a record
  • Data tables with inline editing, custom cell types and row actions
  • Experience Cloud pages for customers and partners
  • Utility bar tools that agents keep open all day

LWC is the default for new UI. Aura still exists in many orgs, and the Aura guide explains when you still need it.

Prerequisites

  • Modern JavaScript. Classes, modules, arrow functions, destructuring and promises. The free JavaScript for LWC course covers exactly that.
  • The Salesforce data model and security basics. See the admin guide.
  • Some Apex. Enough to write an @AuraEnabled method. See Apex.
  • VS Code and the sf CLI, covered in Salesforce DX and VS Code.

What you'll be able to build afterwards

  • Record page components that use Lightning Data Service, with no Apex needed for simple cases
  • Parent-child component trees that communicate with @api properties and custom events
  • Components in unrelated parts of the page that talk through Lightning Message Service
  • Apex-backed components using @wire and imperative calls, with proper error handling
  • Navigation between records, pages and tabs with the navigation service
  • Full mini-apps such as a file uploader and an extended data table

A hands-on example: a record page component with no expressions

This component shows an account's name and revenue on its record page. It uses Lightning Data Service, so there's no Apex.

<template>
    <lightning-card title="Account summary" icon-name="standard:account">
        <div class="slds-p-horizontal_small">
            <template lwc:if={hasError}>
                <p class="slds-text-color_error">{errorMessage}</p>
            </template>
            <template lwc:elseif={isLoaded}>
                <p class="slds-text-heading_small">{name}</p>
                <p>{revenueLabel}</p>
            </template>
            <template lwc:else>
                <lightning-spinner alternative-text="Loading" size="small"></lightning-spinner>
            </template>
        </div>
    </lightning-card>
</template>
import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/Account.Name';
import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue';

export default class AccountSummary extends LightningElement {
    @api recordId;
    account;
    error;

    @wire(getRecord, { recordId: '$recordId', fields: [NAME_FIELD], optionalFields: [REVENUE_FIELD] })
    wiredAccount({ data, error }) {
        if (data) {
            this.account = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.account = undefined;
        }
    }

    get isLoaded() {
        return Boolean(this.account);
    }

    get hasError() {
        return Boolean(this.error);
    }

    get errorMessage() {
        return this.error && this.error.body ? this.error.body.message : 'Could not load the account';
    }

    get name() {
        return getFieldValue(this.account, NAME_FIELD);
    }

    get revenueLabel() {
        const revenue = getFieldValue(this.account, REVENUE_FIELD);
        return revenue ? `Annual revenue: ${revenue.toLocaleString()}` : 'No annual revenue recorded';
    }
}

Why it's built this way:

  • The template has no expressions. Every binding, including {hasError}, {isLoaded} and {revenueLabel}, is a getter or a property. The formatting logic lives in JavaScript, where you can read and test it. More in LWC templates: no expressions, use getters.
  • lwc:if, lwc:elseif and lwc:else replace the older if: directives and make the three states explicit: error, loaded and loading.
  • Fields are imported from @salesforce/schema. Salesforce knows the component depends on those fields, so an admin can't delete one that's in use, and a typo fails at deploy time instead of at runtime.
  • '$recordId' is reactive. The $ prefix tells the wire adapter to re-run when recordId changes. Without it, you'd pass the literal string.
  • Annual revenue is an optional field. With fields, the whole wire fails if the user can't see a field. With optionalFields, that field is simply left out.

To place it on a page, expose the component in its metadata file with the lightning__RecordPage target.

How components talk to each other

Most LWC confusion after the basics is about communication, so it's worth having the rules straight before you build anything bigger:

  • Parent to child: the parent sets a public @api property on the child, or calls a public @api method.
  • Child to parent: the child dispatches a CustomEvent and the parent handles it with an on handler in its template. Data goes in the event's detail.
  • Unrelated components on the same page: publish and subscribe through a Lightning Message Service channel. That also works across LWC, Aura and Visualforce.
  • Record changes: if two components show the same record through Lightning Data Service, they stay in sync automatically. After an Apex update, notify LDS so cached records refresh.

Getting this wrong usually shows up as a child component changing data it doesn't own. Data goes down, events go up.

Common mistakes beginners make

  1. Expressions in templates. {items.length === 0} won't compile. Use a getter such as {isEmpty}.
  2. Using the deprecated if: directives in new code instead of lwc:if, lwc:elseif and lwc:else.
  3. Forgetting the $ in wire parameters, so the wire never reacts to the property changing.
  4. Calling Apex for everything. For single-record reads and writes, Lightning Data Service is faster, cached and respects security for you.
  5. Changing an @api property from inside the child. Data flows down. Fire an event and let the parent own the change.
  6. Bad event names. Use lowercase names with no on prefix, such as select, and document what's in detail.
  7. Querying the DOM too early. this.template.querySelector returns nothing in the constructor. Use it after render.
  8. Ignoring the error branch of a wire, which leaves users staring at a spinner forever.

How LWC connects to the other topics

Who should skip this

  • Skip it if you only configure and automate, and never plan to build UI. Flow screens and Dynamic Forms cover a lot of ground.
  • Skip the core course if you already ship LWCs with LDS, wire adapters and messaging. The real-projects course may still be worth your time.
  • Don't skip the JavaScript course if you're coming from Visualforce or Aura. Most LWC confusion is really JavaScript confusion.

The JavaScript course is free, so start there and judge the teaching before you subscribe. There are no refunds.

Learn it by building it

Every course, every code repository, the discussion group and certificates of completion — one subscription.

Frequently asked questions

How long does it take to learn LWC?

If your JavaScript is solid and you know the Salesforce data model, you can build simple record-page components quickly. Being comfortable with events, wire adapters, Lightning Data Service and Apex together takes a few months of real building.

Should I learn Aura or LWC?

LWC. It's the default for new Salesforce UI. Learn Aura only if you maintain an org that already has Aura components.

Do I need Apex to build Lightning Web Components?

Not for everything. Lightning Data Service handles single-record reads and writes without Apex. You need Apex for complex queries, aggregations, multi-object saves and callouts.

Why can't I use expressions in LWC templates?

LWC templates only bind to properties and getters; they don't evaluate expressions like comparisons or method calls. Move the logic into a getter in the JavaScript class and bind the getter.

Are the old if: template directives still supported in LWC?

The legacy if: directives still work in existing code but are no longer recommended. Use lwc:if, lwc:elseif and lwc:else for new components.

Keep going

Keep me in the loop!

Email me when a new episode is published (promise, I will not spam you)

You're signing up to receive emails from Salesforce Casts