Lightning Web Components Basics
Discover Lightning Web Components
Explain the Lightning Web Components programming model. List the benefits of using Lightning web components. Find what you need to get started developing Lightning web components.- An Open Door to Programming with Web Standards
- Programming with Web Standards - standard technologies like HTML, JavaScript, and CSS are used to build the next generation of Salesforce apps while maintaining compatibility with existing Aura components.
- LWC opens to door to existing technologies
- Capitalization convention Salesforce uses:
- Programming model: “Lightning Web Components”
- Components themselves: “Lightning web components”
- Programming with Web Standards - standard technologies like HTML, JavaScript, and CSS are used to build the next generation of Salesforce apps while maintaining compatibility with existing Aura components.
- Before You Go Further
- This unit requires basic understanding of Salesforce DX projects and Salesforce CLI, which are covered in Quick Start: Lightning Web Components
- Why Lightning Web Components?
- Modern browsers are based on web standards that are constantly improving what browsers can present to a user
- Since LWC is build on code that runs natively in browsers, LWC is lightweight and performant
- Its easier to find solutions to common places on the web, find developers with necessary skills/experience, develop faster, use full encapsulation so components are more versatile
- Browsers have been creating web components for years:
select
,video
,input
- any tags that serve as more than a container
- Simple Component Creation
- Simply create components using HTML, JavaScript, and (optionally) CSS:
- HTML: Provides structure for your component
- JavaScript: Defines the core business logic and event handling
- CSS: Provides the look, feel, and animation for your component
- At a minimum, you just need an HTML file and a Javascript file with the same name in the same folder, also with the same name
- Deploy those to an org with some metadata and Salesforce compiles the files and takes care of the component construction automatically
- Simply create components using HTML, JavaScript, and (optionally) CSS:
HTML
template
tag is a fundamental building block of component’s HMTL - it allows you to store pieces of HTML
<template>
<input value={message}></input>
</template>
JavaScript
- Import statements and class declarations covered below.
import { LightningElement } from 'lwc';
export default class App extends LightningElement {
message = 'Hello World';
}
CSS
- At a minimum only HTML and JavaScript files are needed
input {
color: blue;
}
https://app.lwc.studio/ (previously https://webcomponents.dev/create/lwc)
- The header is a link that lets us try out components, change them, and see immediate results
- You can use GitHub to log in to WebComponents.dev
- “Stories” tab at webcomponents.dev shows the output
- Lightning Web Components and Aura Components Do Work Together
- Over time, Aura components are likely to migrate to the Lightning Web Component model, but in the meantime both are supported.
- Aura components can contain Lightning web components, but not vice versa
- A pure Lightning web components implementation provides full encapsulation and evolving adherence to common standards
- References and Resources
- Salesforce DX tool set
- Scratch Orgs: disposable Salesforce orgs to support development and testing
- Dev Hubs: feature that manages scratch orgs
- Salesforce Command Line Interface (CLI): provides a quick way to run operations for creating and configuring scratch orgs and deploying components
- Lightning Component Library:
- https://developer.salesforce.com/docs/component-library/overview/components: reference for both Aura and Lightning web components and how to use them
- View correct version for your org: http://
.lightning.force.com/docs/component-library
- GitHub: extensions, samples, etc are available through GitHub repos
- Visual Studio Code Salesforce Extension Pack: provides code-hinting, lint warnings, built-in commands
- LWC Recipes: provides a GitHub repo to help you see how web components work
- E-Bikes Demo: end-to-end implementation of Lightning web components to create an app. Can deploy in your own Trailhead Playground
- Lightning Data Service (LDS): access data and metadata from Salesforce. Base Lightning components that work with data are built on LDS
- Lightning Locker: Lightning Locker secures components from one namespace from components in another namespace
- Salesforce DX tool set
- A Lightning web component requires the following files: HTML, JS
- An IDE, like WebComponents.dev, lets you: try your component files in a simulated environment
The following images were taken from a Salesforce blog post introducing LWCs located here.
2014 web stack
2019 web stack
Lightning Web Components
Lightning Web Components versus Aura Components
Create Lightning Web Components
Describe the contents of each component file. Create JavaScript methods for a Lightning web component. Use Lifecycle Hooks in component JavaScript.- A component simply needs a folder and its file with the same name - they’re auto-linked by name and location
- productCard Component in eBikes Sample Repo
- Linked above an example of a data display element - the following breaks down the structure of the files that form the LWC
- All LWCs have a namespace that’s separated from the folder name by a hyphen. Ex: markup for the LWC component with the folder name
app
in the default namespacec
is<c-app>
- But, Salesforce platform doesn’t allow hyphens in the component folder or file names, so
mycomponent
cannot be namedmy-component
. Instead, we use camel case to name itmyComponent
- camelCase component folder names map to kebab-case in markup.
- In markup, to reference aa component with folder name
myComponent
, use<c-my-component>
- Example 1: HTML/Javascript Files
- Lightning web component HTML files all include the
template
tag - these contain the HTML that defines the structure of your component - View examples below by copying/pasting into the appropriate files at webcomponents.dev/create/lwc
- Identifiers in the curly brace
{}
are bound to the fields of the same name in correspondning JavaScript class
- Lightning web component HTML files all include the
HTML File
<template>
<div>
<div>Name: {name}</div>
<div>Description: {description}</div>
<div>Category: {category}</div>
<div>Material: {material}</div>
<div>Price: {price}</div>
<div><img src={pictureUrl}/></div>
</div>
</template>
JavaScript File
import { LightningElement } from 'lwc';
export default class App extends LightningElement {
name = 'Electra X4';
description = 'A sweet bike built for comfort.';
category = 'Mountain';
material = 'Steel';
price = '$2,700';
pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg';
}
- Example 2: HTML/Javascript Files
- Real world example - you want to display data, but it can take time to load. Can use conditional directives within the template to determine which visual elements are rendered.
HTML File
<template>
<div id="waiting" if:false={ready}>Loading…</div>
<div id="display" if:true={ready}>
<div>Name: {name}</div>
<div>Description: {description}</div>
<div>Category: {category}</div>
<div>Material: {material}</div>
<div>Price: {price}</div>
<div><img src={pictureUrl}/></div>
</div>
</template>
JavaScript File
import { LightningElement } from 'lwc';
export default class App extends LightningElement {
name = 'Electra X4';
description = 'A sweet bike built for comfort.';
category = 'Mountain';
material = 'Steel';
price = '$2,700';
pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg';
ready = false;
connectedCallback() {
setTimeout(() => {
this.ready = true;
}, 3000);
}
}
- Base Lightning Web Components
- Generally you don’t want to build all your components ground up - instead you can use a base Lightning web component.
- Example components: field types, display controllers, navigation items, etc
- Replace the div tags for material and category with a
lightning-badge
component:
- Generally you don’t want to build all your components ground up - instead you can use a base Lightning web component.
<template>
<div id="waiting" if:false={ready}>Loading…</div>
<div id="display" if:true={ready}>
<div>Name: {name}</div>
<div>Description: {description}</div>
<lightning-badge label={material}></lightning-badge>
<lightning-badge label={category}></lightning-badge>
<div>Price: {price}</div>
<div><img src={pictureUrl}/></div>
</div>
</template>
- Working with JavaScript
- JavaScript methods define what to do with input, data, events, changes to state, etc, to make your component work
export
statement below defines a class that extends theLightningElement
class- JavaScript file must included at least the following code, where
MyComponent
is the name you assign the component class
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
}
- The LWC Module
- Lightning Web Components uses modules to build functionality and make it accessible to JavaScript in your component file.
- Core module is
lwc
LightningElement
is base class for LWCs, which allows us to useconnectedCallback()
connectedCallback()
is a “lifecycle hook.” This method is triggered when a component is inserted in the document object model (DOM).
- Core module is
- Lightning Web Components uses modules to build functionality and make it accessible to JavaScript in your component file.
// import module elements
import { LightningElement} from 'lwc';
// declare class to expose the component
export default class App extends LightningElement {
ready = false;
// use lifecycle hook
connectedCallback() {
setTimeout(() => {
this.ready = true;
}, 3000);
}
}
- Lifecycle Hooks provide a means of “hooking” your code up to critical events in a component’s lifecycle.
- Component lifecycle includes when a component is:
- Created
- Added to the DOM -
connectedCallback()
- Rendered in the browser
- Encountering errors
- Removed from the DOM -
disconnectedCallback()
- Note that the
this
keyword was used - it refers to the top level of the current context. Above, this context is the class.
- Component lifecycle includes when a component is:
- Decorators - used in JavaScript to modify the behavior of a property/function
- Need to be imported from the
lwc
module. Examples:@api
: marks a field/property as public. Public properties are reactive - the framework observes the property for changes.@track
: tells the framework to observe changes to properties of an object or elements of an array.@wire
: gives you an easy way to get and bind data from a Salesforce org.
- Need to be imported from the
import { LightningElement, api } from 'lwc';
export default class MyComponent extends LightningElement{
@api message;
}
- Example 3: HTML/JavaScript with Decorators
- Following example uses the
@api
decorator to render a value from one component (bike) in another component (app)
- Following example uses the
“App” component HTML
<!-- app.html -->
<template>
<div>
<c-bike bike={bike}></c-bike>
</div>
</template>
“App” component JavaScript
// app.js
import { LightningElement } from 'lwc';
export default class App extends LightningElement {
bike = {
name: 'Electra X4',
picture: 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg'
};
}
“Bike” component HTML
<!-- bike.html -->
<template>
<img src={bike.picture} alt="bike picture" />
<p>{bike.name}</p>
</template>
“Bike” component JavaScript
// bike.js
import { LightningElement, api } from 'lwc';
export default class Bike extends LightningElement {
@api bike;
}
- Resources
- Which of the following is true of the template tag? contains the HTML for your component
- What do you have to include in a component’s JavaScript file? An import statement with the LightningElement wrapper and an export statement with your class name
Deploy Lightning Web Component Files
Configure Lightning web component files for display in an org. Deploy your files to an org. Verify component behavior in an org environment.- Steps to Create an LWC
- Create a project via SFDX: Create Project from VS Code
- Right-click the lwc folder and select SFDX: Create Lightning Web Component
- For this example, name the component LWC, and accept the default location
- Connect Visual Studio to Trailhead by authorizing an org with command SFDX: Authorize an Org in Visual Studio
- Edit the boilerplate
bikeCard.html
,bikeCard.js
, andbikeCard.js-meta.xml
files with the following:
bikeCard.html
<template>
<div>
<div>Name: {name}</div>
<div>Description: {description}</div>
<lightning-badge label={material}></lightning-badge>
<lightning-badge label={category}></lightning-badge>
<div>Price: {price}</div>
<div><img src={pictureUrl}/></div>
</div>
</template>
bikeCard.js
import { LightningElement } from 'lwc';
export default class BikeCard extends LightningElement {
name = 'Electra X4';
description = 'A sweet bike built for comfort.';
category = 'Mountain';
material = 'Steel';
price = '$2,700';
pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg';
}
bikeCard.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- The apiVersion may need to be increased for the current release -->
<apiVersion>52.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>Product Card</masterLabel>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
The Component Configuration File
js-meta.xml
file - provides metadata for Salesforce, including the design configuration for components intended for use in Lightning App Builder- apiVersion is required, and binds the component to a Salesforce API version
- isExposed (true or false) is optional, makes the component available from other namespaces. Only set to true to make a Lightning component usable in these cases:
- From a managed package in Aura
- From a Lightning App Builder in another org
- targets is optional, and specifies which types of Lightning pages the component can be added to in the Lightning App Builder
- targetConfigs is optional, and lets you specify behavior specific to each type of Lightning page, including things like which objects support the component
- Reference these documents for full list of syntax
Example from ebikes repo:
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>52.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>Product Card</masterLabel>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
<target>lightningCommunity__Page</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<objects>
<object>Product__c</object>
</objects>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
Displaying a Component in an Org
- 2 options for displaying a component:
- Set the component to support flexipage types (home, record home, etc)
- Create a tab pointing to an Aura component containing the LWC
Deploy Your Files
- Authenticate with your Dev Hub org using SFDX: Authorize an Org
- Deploy the project files using SFDX: Deploy this Source to Org
Create a New Page for Your Component
- Setup > Quick Find > Lightning App Builder > New > App Page > One Region
- Drag the component “Product Card” onto the page
Handle Events in Lightning Web Components
Create an app that includes multiple components. Describe the file structure of a complex component. Handle events.- Follow an Event’s Journey
- Sample app discussed below has four components working together:
- Tile: displays an individual item
- List: arranges the tiles
- Detail: displays item details when clicked
- Selector: contains the whole set of components
- Sample app discussed below has four components working together:
- Component Composition
- Several zipped up files and folders are provided on the trailhead, shown below (data, detail, list, selector, tile)
- Component Relationships
- In the app, multiple components work together - some components are nested inside other components - Lightning web components can nest inside one another just like HTML elements can nest inside one another
selector.html: lays out the page and renders the list (c-list
) and detail (c-detail
) components
<template>
<div class="wrapper">
<header class="header">Select a Bike</header>
<section class="content">
<div class="columns">
<main class="main" >
<c-list onproductselected={handleProductSelected}></c-list>
</main>
<aside class="sidebar-second">
<c-detail product-id={selectedProductId}></c-detail>
</aside>
</div>
</section>
</div>
</template>
detail.html: conditional rendering (if:true={product}
and if:false={product}
)
<template>
<template if:true={product}>
<div class="container">
<div>{product.fields.Name.value}</div>
<div class="price">{product.fields.MSRP__c.displayValue}</div>
<div class="description">{product.fields.Description__c.value}</div>
<img class="product-img" src={product.fields.Picture_URL__c.value}></img>
<p>
<lightning-badge label={product.fields.Material__c.value}></lightning-badge>
<lightning-badge label={product.fields.Level__c.value}></lightning-badge>
</p>
<p>
<lightning-badge label={product.fields.Category__c.value}></lightning-badge>
</p>
</div>
</template>
<template if:false={product}>
<div>Select a bike</div>
</template>
</template>
list.html: renders several tile (c-tile
) components, one for each bike
<template>
<div class="container">
<template for:each={bikes} for:item="bike">
<c-tile>
key={bike.fields.Id.value}
product={bike}
ontileclick={handleTileClick}>
</c-tile>
</template>
</div>
</template>
list.css: specifies styling of the tiles
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
- Events Up, Properties Down
- In complex components (that contain several parents and children) the components communicate up and down
c-todo-item
child component dispatches an event to the parentc-todo-app
component- Child passes an event object to the parent when a user clicks a button so the parent can handle the event and change the current page
c-todo-app
parent component passes a property or invokes a method in thec-todo-item
component- Parent can set a text value in a child component, or invoke a method in the child component
- In complex components (that contain several parents and children) the components communicate up and down
- Passing Information Up
- Info is passed up using events and event listeners
- Child component dispatches the event and the parent listens for it
- Ex: child component like this one contains a
nextHandler()
method that creates a simple event object usingcustomEvent()
, dispatching the event type ‘next’ when the user clicks a Next button- Event types can be any string but should conform to the DOM event standard of no uppercase letters, no spaces, and underscores to separate words
- Ex: child component like this one contains a
todoItem.js:
import { LightningElement } from 'lwc';
...
nextHandler() {
this.dispatchEvent(new CustomEvent('next'));
}
}
todoApp.html: parent listens for the event with the inline event handler prefixed with on
(onnext
)
<template>
<c-todo-item onnext={nextHandler}></c-todo-item>
</template>
todoApp.js: and passes the event object to an event handler
import { LightningElement } from 'lwc';
export default class TodoApp extends LightningElement {
...
nextHandler(){
this.page = this.page + 1;
}
}
- Passing Information Down
- Info can be passed down using public properties and public methods
- Example 1: Public Properties
- Make a component property public by prefacing it with
@api
decorator, then set the public property by an external component - Note: property names in JavaScript are in camel case while HTML attribute names are in kebab case (dash-separated) to match HTML standards
- Public properties are good for passing down primitive values, simple objects, and arrays
- Make a component property public by prefacing it with
todoItem.js: c-todo-item
child component
import { LightningElement, api } from 'lwc';
export default class TodoItem extends LightningElement {
@api itemName;
}
todoApp.html: set value from the parent
<template>
<c-todo-item item-name="Milk"></c-todo-item>
</template>
- Example 2: Public Properties
- Use getters and setters to execute logic when properties are get or set - annotate them with the
@api
decorator to make them public for other components
- Use getters and setters to execute logic when properties are get or set - annotate them with the
videoPlayer.js: child component
import { LightningElement, api } from 'lwc';
export default class VideoPlayer extends LightningElement {
@api
play() {
// Play music!
}
}
methodCaller.js: when c-video-player
component is included in a parent, invoke the method from the parent like this:
handlePlay()
was defined and fires the eventquerySelector()
DOM method is used to search for a DOM element calledc-video-player
and invoke its public method
import { LightningElement } from 'lwc';
export default class MethodCaller extends LightningElement {
handlePlay() {
this.template.querySelector('c-video-player').play();
}
}
- Handling Events in HTML
- Imagine the selector app needs to handle one type of event - user clicking a tile. Two options:
- Handle events in HTML: add an event listener in the template (HTML is recommended)
- JavaScript: write an event listener function (not recommended)
- Imagine the selector app needs to handle one type of event - user clicking a tile. Two options:
tile.html: each tile component listens for the user click because the tile component contains an onclick
event listener
<template>
<div class="container">
<a onclick={tileClick}>
<div class="title">{product.fields.Name.value}</div>
<img class="product-img" src={product.fields.Picture_URL__c.value}></img>
</a>
</div>
</template>
tile.js: onclick
listener calls the handler function tileClick
in the tile.js JavaScript file
import { LightningElement, api } from 'lwc';
export default class Tile extends LightningElement {
@api product;
tileClick() {
const event = new CustomEvent('tileclick', {
// detail contains only primitives
detail: this.product.fields.Id.value
});
// Fire the event from c-tile
this.dispatchEvent(event);
}
}
- Selector App Event Pattern
- The product selector app demoed on Salesforce is a complex component (one with several parent and child components)
- Salesforce recommends propagating the event up through the component hierarchy, so parent components can respond to child events
- If you have other child components (aside from the one firing the event), you can pass a property down to those children in response
- To accomplish this, you need to chain event listeners and handlers up the hierarchy to the ebikes component, then pass a property down to the detail component - see the pattern below
- The product selector app demoed on Salesforce is a complex component (one with several parent and child components)
- tile.html has
onclick
event listener that callstileClick
handler
<template>
<div class="container">
<a onclick={tileClick}>
<div class="title">{product.fields.Name.value}</div>
<img class="product-img" src={product.fields.Picture_URL__c.value}></img>
</a>
</div>
</template>
- tile.js has
tileClick
method that creates a newCustomEvent
with typetileClick
and an object containing adetail
value (this.product.fields.Id.value
)
import { LightningElement, api } from 'lwc';
export default class Tile extends LightningElement {
@api product;
tileClick() {
const event = new CustomEvent('tileclick', {
// detail contains only primitives
detail: this.product.fields.Id.value
});
// Fire the event from c-tile
this.dispatchEvent(event);
}
}
- list.html has
ontileclick
listener that calls thehandleTileClick
handler
<template>
<div class="container">
<template for:each={bikes} for:item="bike">
<c-tile>
key={bike.fields.Id.value}
product={bike}
ontileclick={handleTileClick}>
</c-tile>
</template>
</div>
</template>
- list.js has the
handleTileClick
method that passes in the event (evt
) to create anotherCustomEvent
(productselected
) with an object also containing adetail
valueevt.detail
. It dispatches the event in JavaScript.
import { LightningElement } from 'lwc';
import { bikes } from 'c/data';
export default class List extends LightningElement {
bikes = bikes;
handleTileClick(evt) {
// This component wants to emit a productselected event to its parent
const event = new CustomEvent('productselected', {
detail: evt.detail
});
// Fire the event from c-list
this.dispatchEvent(event);
}
}
- selector.html has the
onproductselected
event listener that calls thehandleProductSelected
handler
<template>
<div class="wrapper">
<header class="header">Select a Bike</header>
<section class="content">
<div class="columns">
<main class="main" >
<c-list onproductselected={handleProductSelected}></c-list>
</main>
<aside class="sidebar-second">
<c-detail product-id={selectedProductId}></c-detail>
</aside>
</div>
</section>
</div>
</template>
- selector.js has the
handleProductSelected
method setselectedProductId
to theevt.detail
value that was passed into it
import { LightningElement } from 'lwc';
export default class Selector extends LightningElement {
selectedProductId;
handleProductSelected(evt) {
this.selectedProductId = evt.detail;
}
}
- detail.html has a conditional directive waiting for a product value
<template>
<template if:true={product}>
<div class="container">
<div>{product.fields.Name.value}</div>
<div class="price">{product.fields.MSRP__c.displayValue}</div>
<div class="description">{product.fields.Description__c.value}</div>
<img class="product-img" src={product.fields.Picture_URL__c.value}></img>
<p>
<lightning-badge label={product.fields.Material__c.value}></lightning-badge>
<lightning-badge label={product.fields.Level__c.value}></lightning-badge>
</p>
<p>
<lightning-badge label={product.fields.Category__c.value}></lightning-badge>
</p>
</div>
</template>
<template if:false={product}>
<div>Select a bike</div>
</template>
</template>
- detail.js brings the pieces together, creating a private variable
productId
to track the state of theproductId
value. Then it uses a get/set pattern to get the value and set it to a variableproduct
which lets detail.html load the conditional content
import { LightningElement, api } from 'lwc';
import { bikes } from 'c/data';
export default class Detail extends LightningElement {
// Ensure changes are reactive when product is updated
product;
// Private var to track @api productId
_productId = undefined;
// Use set and get to process the value every time it's
// requested while switching between products
set productId(value) {
this._productId = value;
this.product = bikes.find(bike => bike.fields.Id.value === value);
}
// getter for productId
@api get productId(){
return this._productId;
}
}
- Deploy Your Files to Your Org
- Right click the default folder and select SFDX: Deploy Source to Org to move the source code to the org
- Right click the default folder and select SFDX: Deploy Source to Org to move the source code to the org
- The following nests one component inside another:
<c-detail product-id={selectedProductId}></c-detail>
- The following describes an event handling pattern in a complex component app: Events are dispatched up from child to parent, then properties are passed down from parent to child
Add Styles and Data to a Lightning Web Component
Use CSS and Lightning Design System with a component. Get data from a Salesforce org. Deploy your app to an org and test it.- Adapt Your Component
- This unit demos how to control a component’s appearance and pull in live data from Salesforce
- CSS and Component Styling
- CSS for Lightning Web Components adheres to W3C standard - its automatically applied to the corresponding HTML file
- “Shadow DOM” is a mechanism that allows Lightning Web Components to encapsulate components, keeping them separate from the global DOM
detail.css: after adding the following, compare it to the detail section above
body{
margin: 0;
}
.price {
color: green;
font-weight: bold;
}
- Applying Lightning Design System Styles
- Salesforce Lightning Design System (SLDS) is a CSS framework that provides a look and feel consistent with Lightning Experience
- Following code snippet updates detail.html file to use
slds-text-heading_small
andslds-text-heading_medium
fot settings - see result below
<template>
<template if:true={product}>
<div class="container">
<div class="slds-text-heading_small">{product.fields.Name.value}</div>
<div class="price">{product.fields.MSRP__c.displayValue}</div>
<div class="description">{product.fields.Description__c.value}</div>
<img class="product-img" src={product.fields.Picture_URL__c.value}></img>
<p>
<lightning-badge label={product.fields.Material__c.value}></lightning-badge>
<lightning-badge label={product.fields.Level__c.value}></lightning-badge>
</p>
<p>
<lightning-badge label={product.fields.Category__c.value}></lightning-badge>
</p>
</div>
</template>
<template if:false={product}>
<div class="slds-text-heading_medium">Select a bike</div>
</template>
</template>
- Get Salesforce Data
- Lightning Web Components use a reactive wire service which is build on Lightning Data Service
- The Wire Service Brings Data to Your App
@wire
decorator implements the wire service for your app - to use it:- Import a wire adapter in the JavaScript file
- Decorate a property or function with the
@wire
decorator
- The syntax follows:
adapterId
: Identifier, identifier of the wire adapteradapter-module
: String, identifier of the module that contains the wire adapter functionadapterConfig
: Object, a configuration object specific to the wire adapterpropertyOrFunction
: private property or function that receives the stream of data from the wire service.- If a property is decorated with
@wire
the results are returned to the property’s data or error property - If a function is decorated with
@wire
, the results are returned in an object with a data property and an error property
- If a property is decorated with
General Syntax:
import { adapterId } from 'adapter-module';
@wire(adapterId, adapterConfig)
propertyOrFunction;
selector.js:
- Line 1 imports the
wire
service fromlwc
- Line 2 imports the adapterId and adapter-modules for
getRecord
andgetFieldValue
fromlightning/uiRecordApi
- Line 3 imports the current User Id using the
@salesforce
module - Line 4 imports the
@salesforce
scheme forUser.Name
- Line 12 uses the
@wire
decorator to use the wire service to callgetRecord
passing in theuserId
and getting thefields
- Line 13 sets
user
as the receiver for the@wire
call
import { LightningElement, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import Id from '@salesforce/user/Id';
import NAME_FIELD from '@salesforce/schema/User.Name';
const fields = [NAME_FIELD];
export default class Selector extends LightningElement {
selectedProductId;
handleProductSelected(evt) {
this.selectedProductId = evt.detail;
}
userId = Id;
@wire(getRecord, { recordId: '$userId', fields })
user;
get name() {
return getFieldValue(this.user.data, NAME_FIELD);
}
}
selector.html: edited to include the name
<template>
<div class="wrapper">
<header class="header">Available Bikes for {name}</header>
<section class="content">
<div class="columns">
<main class="main" >
<c-list onproductselected={handleProductSelected}></c-list>
</main>
<aside class="sidebar-second">
<c-detail product-id={selectedProductId}></c-detail>
</aside>
</div>
</section>
</div>
</template>
- Mobile-Friendly Markup
- Salesforce recommends designing for mobile first, using Salesforce’s mobile preview tools, then designing for desktop
- Salesforce recommends designing for mobile first, using Salesforce’s mobile preview tools, then designing for desktop
More Resources:
- Lightning Web Components Developer Guide: Introducing Lightning Web Components
- Developers: Code Samples and SDKsTrailhead Sample Gallery
- Trailhead: JavaScript Skills for Salesforce Developers
- Lightning Web Components Developer Guide: Create Mobile-Ready Components
- Lightning Web Components Developer Guide: Style Components with Lightning Design System
- Lightning Web Components Developer Guide: Preview Lightning Web Components on Mobile
- Lightning Web Components Developer Guide: Shadow DOM
- Lightning Web Components Developer Guide: Use the Wire Service to Get Data
- Lightning Web Components Developer Guide: @salesforce Modules