12.3 Lightning Web Components Fundamentals

Key Takeaways

  • An LWC bundle typically includes .html template, .js module, optional .css, and .js-meta.xml configuration
  • @api exposes public properties; modern LWC reactivity tracks field changes without legacy @track on primitives/objects in most cases; @wire declaratively provisions data
  • Shadow DOM encapsulates component markup and CSS so styles do not leak in or out by default
  • Prefer base Lightning components and SLDS patterns for consistent, accessible UI
  • js-meta.xml controls isExposed, targets (App Builder pages, record pages, utilities), and public property definitions for admins
Last updated: August 2026

12.3 Lightning Web Components Fundamentals

Quick Answer: A Lightning Web Component is a folder with componentName.html, componentName.js, optional componentName.css, and componentName.js-meta.xml. Use @api for public properties, modern reactive fields (and @track only when still required for legacy nested mutation patterns), and @wire for declarative data. Shadow DOM encapsulates DOM/CSS. Expose components to App Builder with isExposed and targets in the meta file. Prefer base Lightning components and SLDS.

This section is the core LWC vocabulary for Platform Developer I User Interface questions. Section 12.4 extends into Apex wire, imperative calls, LDS, and events.

LWC File Structure

Example bundle accountSummary:

accountSummary/
  accountSummary.html
  accountSummary.js
  accountSummary.css
  accountSummary.js-meta.xml
FilePurpose
.htmlTemplate markup with directives (lwc:if, for:each, etc. depending on API version patterns you study) and bindings
.jsES module exporting a class extending LightningElement
.cssStyles scoped to the component via Shadow DOM
.js-meta.xmlMetadata: API version, exposure, targets, properties

Naming rules matter: the folder name, HTML root tag usage, and JavaScript class naming follow LWC conventions (kebab-case in markup, camelCase class names).

HTML template essentials

<!-- accountSummary.html -->
<template>
    <lightning-card title={cardTitle}>
        <div class="slds-p-around_medium">
            <p>{accountName}</p>
            <lightning-button label="Refresh" onclick={handleRefresh}></lightning-button>
        </div>
    </lightning-card>
</template>

Notes:

  • The root is a <template> wrapper
  • Bind properties with {propertyName} (no this. in the template)
  • Bind event handlers with {handlerName}
  • Use base components like lightning-card and lightning-button when possible

JavaScript module essentials

// accountSummary.js
import { LightningElement, api } from 'lwc';

export default class AccountSummary extends LightningElement {
    @api recordId;
    @api cardTitle = 'Account Summary';

    accountName = 'Loading…';

    handleRefresh() {
        // imperative logic or refresh wires (see 12.4)
    }
}
  • One default export class extending LightningElement
  • Import decorators and modules from 'lwc' or Lightning platform modules
  • Class fields hold reactive state for the template

CSS

/* accountSummary.css */
:host {
    display: block;
}
p {
    font-weight: 600;
}

Styles apply inside the component’s shadow tree. They do not freely style parent page DOM, and outer CSS does not casually restyle your internal elements the way global Visualforce stylesheets often did.

Meta configuration (js-meta.xml)

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>62.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Account Summary</masterLabel>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage">
            <property name="cardTitle" type="String" label="Card Title" />
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>
Meta conceptMeaning
isExposedtrue makes the component available for selection in supported builders when targets allow
targetsWhere it can be placed (record page, app page, home page, utility bar, Flow screens, etc.)
propertiesApp Builder-configurable public inputs (align with @api fields)
apiVersionComponent API version

Exam trap: A component with perfect JS/HTML but isExposed=false (or missing the right target) will not appear in App Builder for that page type.

Decorators and Reactivity

@api — public reactive properties

@api marks a field as a public property that parents (or App Builder) can set:

import { LightningElement, api } from 'lwc';

export default class ChildPanel extends LightningElement {
    @api heading;
    @api recordId; // often provided on record pages when configured
}

Parent markup:

<c-child-panel heading="Details" record-id={recordId}></c-child-panel>

HTML attribute names are kebab-case; JavaScript properties are camelCase (record-idrecordId).

Public properties are part of the component’s contract. Prefer @api for inputs; keep internal state on non-@api fields.

Modern reactivity and @track

In modern LWC, class fields used in the template are reactive for reassignment. Historically, @track was required to make objects/arrays deeply reactive. Today:

  • Reassigning a field (this.contacts = [...newList]) triggers rerender
  • Mutating a nested property in place (this.contacts[0].Name = 'x') may not trigger UI updates unless you use patterns that establish reactivity correctly
  • @track still appears in older code and some exam materials for tracking mutations on plain objects/arrays

Exam-ready guidance:

  1. Prefer immutable updates (spread new objects/arrays) so reactivity is obvious
  2. Recognize @track when shown on an object field in legacy snippets
  3. Do not confuse @track (internal reactivity) with @api (public surface)
import { LightningElement, track } from 'lwc';

export default class FilterPanel extends LightningElement {
    // Modern style: reassign fields
    filters = { status: 'Open', ownerId: null };

    // Legacy-style annotation still seen in materials
    @track draft = { name: '' };

    setStatus(status) {
        this.filters = { ...this.filters, status }; // reactive reassignment
    }
}

@wire — declarative data provisioning

@wire connects a property or function to a Lightning data adapter (Apex wire-enabled method, uiRecordApi, and others):

import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/Account.Name';

export default class AccountSummary extends LightningElement {
    @api recordId;

    @wire(getRecord, { recordId: '$recordId', fields: [NAME_FIELD] })
    account;

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

Wire fundamentals:

  • Reactive parameters use '$recordId' syntax so the wire re-fires when recordId changes
  • Wired property receives { data, error } shape
  • Wired function form lets you handle data/error in a method body
  • Section 12.4 covers Apex wire, imperative Apex, and error patterns in depth

Other common imports (recognize on sight)

ImportRole
LightningElementBase class
api, wire, trackDecorators
lightning/uiRecordApiLDS-style record access
@salesforce/schema/...Compile-time field/object references
@salesforce/apex/...Import Apex methods

Shadow DOM Encapsulation

LWC renders into Shadow DOM, which:

  • Scopes CSS to the component
  • Hides internal DOM structure from casual external queries
  • Encourages communication via @api and events, not DOM scraping

Implications:

  • Global page CSS should not be your primary styling strategy for component internals
  • Parent components should not rely on querySelector into a child’s private DOM for business logic
  • Use this.template.querySelector inside the component to access its own template elements when needed

Lightning Web Security / Locker-related constraints reinforce isolation between namespace components. Exam language often frames this as encapsulation and security of the component boundary.

Base Lightning Components and SLDS

Base Lightning components (lightning-*) wrap SLDS and platform behavior:

  • Inputs: lightning-input, lightning-combobox, lightning-textarea
  • Data: lightning-datatable, lightning-tree-grid
  • Record UI: lightning-record-form, lightning-record-view-form, lightning-record-edit-form, lightning-input-field
  • Layout/chrome: lightning-card, lightning-layout, lightning-tabset
  • Feedback: lightning-spinner, toast via ShowToastEvent

Why exams prefer them: accessibility hooks, SLDS consistency, less custom CSS, and tighter platform integration (especially record forms with FLS-aware fields).

You may still apply SLDS utility classes in markup (slds-grid, slds-p-around_medium) for layout. Prefer utilities + base components over reinventing Salesforce look-and-feel with ad-hoc CSS.

Composition and Lifecycle (High-Yield)

  • Nest components as custom elements: <c-child-panel></c-child-panel>
  • Pass data down with @api
  • Send data up with CustomEvent (12.4)
  • Lifecycle hooks such as connectedCallback, disconnectedCallback, and renderedCallback appear in scenarios about initialization and cleanup—use them carefully (renderedCallback can run often; avoid infinite loops)
connectedCallback() {
    // runs when component is inserted into the DOM
}

Common Exam Traps

TrapCorrection
Forgetting js-meta.xml targetsComponent never shows in App Builder
Using @api for private temporary stateUse internal fields instead
Expecting in-place array mutation to always refresh UIReassign arrays/objects
Styling parent page from component CSSShadow DOM scopes styles
Building custom HTML tables when lightning-datatable fitsPrefer base components
Confusing Aura v. / c. expressions with LWC {field} bindingsDifferent template languages

Minimal End-to-End Picture

  1. Author html/js/css/meta bundle
  2. Expose with isExposed + targets
  3. Accept recordId / config via @api
  4. Load data with @wire or imperative Apex (12.4)
  5. Render with base components + SLDS utilities
  6. Communicate with events and public properties

Bottom line: LWC fundamentals are four key files, decorators (@api, reactivity/@track, @wire), Shadow DOM encapsulation, base Lightning components + SLDS, and meta.xml exposure/targets. Master these before drilling data access patterns in the next section.

Test Your Knowledge

Which files are part of a typical Lightning Web Component bundle?

A
B
C
D
Test Your Knowledge

What is the primary purpose of the @api decorator in LWC?

A
B
C
D
Test Your Knowledge

A developer builds an LWC but cannot find it in the Lightning App Builder component list for a record page. Which meta configuration issue is the most likely cause?

A
B
C
D