DEX 602 v.1 Summer'21 Student Guide
DEX 602 v.1 Summer'21 Student Guide
Day One
15 minutes Introductions
15 minutes Wrap Up
Agenda
Program Lightning Web Components (DEX602)
Day Two
15 minutes Wrap Up
Agenda
Program Lightning Web Components (DEX602)
Day Three
15 minutes Wrap Up
Agenda
Program Lightning Web Components (DEX602)
Day Four
15 minutes Wrap Up
Agenda
Program Lightning Web Components (DEX602)
Day Five
2
Forward Looking Statements
3
Introductions 4
LESSON 1:
Course Introduction
LESSON 2:
Lightning Web Components
LESSON 3:
Surface Lightning Web Components
LESSON 4:
Navigation and Layouts
LESSON 5:
Advanced Components
LESSON 6:
Work with Data
LESSON 7:
Source-Tracked Orgs
LESSON 8:
Lightning Web Components for Aura Developers
Lesson 1:
Course Introduction
Lesson 1: Course Introduction 9
• Course Objectives
• Course Prerequisites
• System Requirements
• Class Project
• Review the Application
• Introduction to Salesforce DX and Git
• Exercise 1-1: Meeting the Prerequisites
Course Objectives 10
Concepts
Walkthroughs
Summaries
Reviews
Best Practices
Welcome 14
Account Contact
c-student-detail
c-student-browser
c-student-browser-form
c-student-tile c-student-tiles
Class Project – Grid View 17
Class Project – Student Certification View 18
Class Project – Trip Reports View 19
Class Project – Trip Reports Form 20
Salesforce DX 21
Source-Centric Development
Greater agility to test out features with confidence
Team Collaboration
Increased dev productivity, faster time to market
Development Options
Visual Studio Code, IntelliJ,
Welkin, Cloud9, and more
Scratch Org
• Production
• Dev Hub trial
• Developer Edition
Functionalities of the Salesforce CLI 26
Key Benefits
Single interface for all Salesforce DX features
Improved developer productivity
Integration with VCS, CI, and other toolsets
Salesforce CLI Commands and Parameters 27
Command Palette is
used to execute
commands.
Salesforce Extensions
plugin bundle installed.
Overview of Visual Studio Code: GitLens 36
GIT
Deploy Production
Local
Remote Repository Sandbox
Repository
Staging
Pull
Development Environment 41
SFDX
c:\
Connect Create
Dev Hub Org Scratch Org
Push/Pull
Author
Code
You can set CLI runtime configuration values for your current project
(local variables) or for all projects (global variables).
defaultusername Username for a scratch org that all commands run against by default.
defaultdevhubusername Username for a Dev Hub org that the force:org:create command uses.
TIPS:
Setting defaultusername in each Salesforce DX project simplifies CLI commands by not having
to always specify the scratch org’s alias or username in the command.
Global vs Local Values 43
Global Values
• Apply to all projects on your computer.
Local Values
• Apply to a specific project
• Override global settings when commands are run from within a Salesforce
DX project directory.
sfdx-project.json
1{ Indicates the targeted directories when
2 "packageDirectories": [ syncing to and from the source-tracked
3 { org.
4 "path": "force-app/Base",
5 "default": false
All directories are used
6 },
for PUSHING source.
7 {
8 "path": "force-app/Exercises",
Set the default
9 "default": true
property to true to
10 }
specify the directory
11 ],
for PULLING source.
12 "namespace": "",
13 "sfdcLoginUrl": "https://login.salesforce.com",
14 "sourceApiVersion": "52.0"
15 }
Base Metadata 45
A permission set
Standard Object Customizations
and Custom Object Definitions
Exercise Metadata 46
Some parts of
objects are Object fields in
extracted into individual files
subdirectories
* Branch Structure for Class Exercises 48
Student
Start SLN_07
Solutions
Student2
Exercise 1-1: Meet the Prerequisites 49
Goal:
Install and configure the required software for the course.
Tasks
1. Download LWC_Exercises.zip 6. Register Dev Hub
2. Configure your User Account 7. Logout from Dev Hub
3. Enable Dev Hub 8. Setup Scratch Org
4. Import Org project into VSCode 9. Commit your changes
5. Create new Git Branch
100 minutes
Lesson Summary 50
2014 2019
Lightning Component Framework and Lightning Web Components
Aura programming model launched launched
Web Standards
Renaissance
What are Lightning Web Components? 54
• Unparalleled performance
Aura and Lightning Web Components Interoperability 55
1 ({ Aura
2 count: function(component, event, helper) {
3 let greeting = component.get("v.greeting");
4 alert(greeting.length + " letters");
5 }
6 })
webcomponents.dev 59
2
3
1
RESOURCE:
https://webcomponents.dev/
Lightning Mini Playground 60
https://trailhead.salesforce.com/sample-gallery
Review OOTB Lightning Web Components 62
RESOURCE:
https://<mySalesforceInstance>.lightning.force.com/docs/component-library
Exercise 2-1: Review the Available Components 63
Goals:
Review OOTB Lightning Web Components.
10 minutes
Lesson 2: Lightning Web Components 64
CSS Module
myComponent.js-meta.xml
• Required
• CSS
• Metadata
Client and Server Architecture 68
Logic
Server
Apex Classes
Data
Standard and
Custom Objects
Basic UI Component - JavaScript File 69
myComponent.js
1 import { LightningElement } from 'lwc';
2 export default class MyComponent extends LightningElement {}
Class name in
PascalCase
Basic UI Component - HTML File 70
myComponent.js
1 import { LightningElement } from 'lwc';
2 export default class MyComponent extends LightningElement {}
parentComponent.html
1 <template>
2 <!–- HTML code -->
3 <c-my-component></c-my-component>
4 </template>
NOTE:
The template element is used to declare fragments of HTML that can be rendered at runtime.
Basic UI Component - CSS File 71
.boxSmall {
width: 100px;
height: 100px;
margin: auto;
background-color: #F0F1F2;
}
PascalCase, camelCase or kebab-case ? 72
parentComponent.html
1 <template>
2 <c-my-component one-attribute="1"></ c-my-component>
3 </template>
myComponent.js
1 import { LightningElement, api } from 'lwc';
2 export default class MyComponent extends LightningElement {
3 @api oneAttribute;
4 }
Use Lightning App Builder 73
Configuration File 74
myComponent.js-meta.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
3 <apiVersion>52.0</apiVersion>
4 <isExposed>true</isExposed>
5 <targets>
6 <target>lightning__AppPage</target>
7 </targets>
8 </LightningComponentBundle>
NOTE:
This is the basic metadata for a component that will be used on the Lightning App Builder.
Generate a Password to Allow Login 75
via the Salesforce App
$ sfdx force:user:password:generate
Successfully set the password ‘_3mafV3cqb’ for user ‘test@example.com’
AwInstructors App Page (Main Region & Right Sidebar) added to Certification App
student-browser-form
new custom component
student-browser
new custom component
lightning-tabset
lightning-tab Chatter Feed
standard standard component
components
Exercise 2-2: Create a Lightning Web Component 77
Tasks:
1. Define a Component that is 4. Deploy the Student Browser
Surfaced in Lightning App Builder Component as a Custom
2. Define the Student Browser Tab in Lightning Experience
Form Component
3. Invoke the Student Browser 25 minutes
Form Component
Lesson 2: Lightning Web Components 78
• Style Components
• Define Component Properties
• Handle DOM Events
• Debug Lightning Web Components
• Work with Salesforce Data
• Use Base Lightning Components
• Raise and Handle Events
• Advanced Communication between Components
Style Lightning Web Components 79
CSS
• Create a style sheet in the component folder
• The style sheet name must be the same as the name of the component
• Automatically applied
• Scoped to the current component ONLY (Shadow DOM)
CSS Basics in Lightning Web Components 80
studentBrowserForm.html studentBrowserForm.css
Considerations
LWC CSS does not require the .THIS keyword
The .className selector is supported.
The #ID selector is not supported because id values may be transformed into globally
unique values when the template is rendered.
CSS Scope 81
parent.html child.html
1 <template> 1 <template>
2 <h1>Parent h1</h1> 2 <h1>Child h1</h1>
3 <c-child></c-child> 3 </template>
4 </template>
Parent h1
3 }
Child h1
NOTE:
Due to the Shadow DOM (to be discussed later), CSS styles defined in a parent component
don’t reach into a child.
CSS :host Selector 82
child.html parent.html
1 <template> 1 <template>
2 <div>Hello from Child</div> 2 <div>Hello from Parent</div>
3 </template> 3 <c-child></c-child>
4 </template>
NOTE:
A component’s style sheet can reach up and style its own element. In this example, child.css is
used to style c-child, but instead of using a c-child selector, we use the :host selector.
Share CSS Rules between Components 83
1 h1 {
2 color: #FF0000;
3 }
2 Import the shared CSS file from another component's CSS file.
studentBrowserForm.css
2 Use the token in a CSS variable with --c- as the prefix in the name.
1 .crazycomic { studentBrowserForm.css
2 font-family: Comic Sans MS;
3 text-shadow: 2px 2px #c0c0c0;
4 color: var(--c-brandColor);
5 }
Style Components with Custom Styling Hooks 85
Style hooks allow you to customize the look and feel of base
components. studentBrowserForm.html
URL PATH:
http://www.lightningdesignsystem.com
* Apply SLDS Classes 87
BEM (Block-Element-Modifier):
• Block represents a high-level component (e.g. slds-button)
• Element represents a descendent of a component (e.g. slds-button__icon)
• Modifier represents a different state of a block or element (e.g. slds-button_neutral)
1 <template>
2 <lightning-button-group>
3 <lightning-button label="Refresh"></lightning-button>
4 <lightning-button label="Edit"></lightning-button>
5 <lightning-button label="Save"></lightning-button>
6 </lightning-button-group>
7 </template>
1 <template>
2 <div style="width:300px; height:300px;
3 border:1px solid black; margin:5px;"
4 class="slds-align_absolute-center"> Centered Content
5 Centered Content
6 </div>
7 </template>
Use SLDS Icons 89
Refer to icons as
categoryname:iconname
Variations
Output
Blueprints
NOTE: Blueprints contain markup for different variations or states of the same component.
Change Background in Lightning Experience 91
Background Color and Image 92
There are two ways to adjust the background color and image.
student-browser-form student-browser
custom component custom component
Exercise 2-3: Theme a Lightning Web Component 94
During this exercise, you will theme the components that you
developed in the previous exercise.
Tasks:
1. Review the capabilities of 4. Use SLDS to apply padding within
lightning-card a component
2. Use lightning-card to add contrast 5. Apply custom CSS
to the search form
3. Use SLDS to add margin to
a component 30 minutes
Lesson 2: Lightning Web Components 95
Property
Only available within the Decorate with @api Decorate with @api
component. Set <isExposed> false on Set <isExposed> true
Either no decorator or component. on component.
@track.
NOTE:
Setting <isExposed>true</isExposed> also makes the component global
and eligible for App Builder and other targets.
Reactivity in Private Properties with no Decorator 99
1 <template> hello.html
2 <div>{greeting}, {name.first}!</div>
3 <lightning-button label="Change Message" onclick={handleClick}>
4 </lightning-button>
5 </template>
NOTE:
JavaScript primitive types include string, integer, and boolean.
Use the @track Decorator on Objects and Arrays 100
NOTE:
A public property can be set in Lightning App Builder, or by a parent component that
uses the component in its markup.
Instructor Demo: Reactivity in Arrays 102
• propsDemo/propsDemo.html
• propsDemo/propsDemo.js
Getters 103
1 <template> myComponent.html
2 <div class={tileSelected} >
3 ...
4 </div>
5 </template>
Setters 104
Data Binding
hello.html
1 <template>
2 <lightning-input label="Name" name="name"></lightning-input>
3 </template>
hello.js
1 import { LightningElement} from 'lwc';
2 export default class HelloBinding extends LightningElement {
3 greeting = 'World';
4 }
Input Field with One-Way Data Binding 107
1 <template> hello.html
2 <lightning-input label="Name" value={greeting}>
3 </lightning-input>
4 </template>
Add an onchange handler and update the property to bind data both ways.
hello.html
1 <template>
2 <lightning-input label="Name" value={greeting} onchange={handleChange}>
3 </lightning-input>
4 </template>
hello.js
1 import { LightningElement} from 'lwc';
2 export default class HelloBinding extends LightningElement {
3 greeting = 'World';
4 handleChange(event) {
5 this.greeting = event.target.value;
6 }
7}
Define Properties and Functions 109
• Each time a reactive property is updated, all getter functions are re-
evaluated (even when that reactive property is not used in the getter).
• A wired service is reactive, if it uses a reactive variable (prefixed with $).
• Object and arrays have special reactivity rules when not using @track
Work with Boolean Values in Components 110
… child.js
@api isSelected = false;
…
is equivalent to is equivalent to
student-tile student-browser
new custom custom component
component
Exercise 2-4: Work with Component Properties 112
During this exercise, you will start building the student gallery.
Tasks:
1. Define the studentTile component.
2. Define component properties.
3. Generate dynamic markup.
20 minutes
Lesson 2: Lightning Web Components 113
studentTile.html
1 <template>
2 <button class={tileSelected} onclick={onStudentClick}>
3 …
4 </button>
5 </template>
studentTile.js
1 onStudentClick(){
2 alert(this.student.Name);
3 }
for:each
1 <template>
2 <template for:each={studentList} for:item="student" for:index="idx">
3 <div key={student.Id}>
4 {idx}. {student.Name}
5 </div>
6 </template>
7 </template>
1 <template> iterator
2 <template iterator:it={studentList}>
3 <div key={it.value.Id}>
4 <div if:true={it.first} class="list-first"></div>
5 {it.index}. {it.value.Name}<br/>
6 <div if:true={it.last} class="list-last"></div>
7 </div>
8 </template>
9 </template>
What is a Lifecycle Hook? 118
Lifecycle Hook
1 constructor() { studentBrowser.js
2 super();
3 const studentNames = ['Rad', 'Stuart', 'Andres', 'Rahul', 'Amit', 'Simon'];
4 this.studentList = studentNames.map( (studentName, index) => {
5 return {
6 'sobjectType': 'Contact',
7 'Name': studentName,
8 'PhotoUrl': '/services/images/photo/003B0FakePictId',
9 'Id': index
10 };
11 });
12 }
connectedCallback() function 120
studentDetail.js
1 connectedCallback() {
2 if(this.subscription){
3 return;
4 }
5 this.subscription = subscribe(this.messageContext,
6 SELECTED_STUDENT_CHANNEL, message => {
7 this.handleStudentChange(message);
8 });
9 }
NOTE: The connectedCallback() hook can fire more than once. For example, it will fire again
if you remove an element and then insert it into another position (example: reordering a list).
* constructor() vs connectedCallback() – Host Element 121
You can add attributes to the host element during any stage of the
component lifecycle other than construction.
constructor() constructor()
called on parent called on child
Properties Properties
Assigned Assigned
connectedCallback() connectedCallback()
called on parent called on child
render() render()
called on parent called on child
renderedCallback() renderedCallback()
called on parent called on child
Lifecycle Hooks when a Component is 124
Removed from the DOM
Parent removed
from the DOM
disconnectedCallback()
called on parent
Child Removed
from DOM
disconnectedCallback()
called on child
Common Lifecycle Hook Use Cases 125
onclick
student-tile student-tiles
custom component new custom component student-browser
custom component
Exercise 2-5: Handle DOM Events 128
During this exercise, you will implement a click handler and use
sample data to test out the gallery function.
Tasks:
1. Handle an initialization event
2. Modify the contents of a tracked property
3. Iterate through a list of JavaScript objects
4. Handle a User Event
5. Access a property in the handler
30 minutes
EXTRA CREDIT Reinforce your Skills with a Challenge 129
Comfortable with
Components Challenge 1: Output the Date and Time
Scenario
Create a component challenge_currentDateTime that
displays the current date and time when the page
loads on a lightning-card.
40 min
Lesson 2: Lightning Web Components 130
Default Yes No
CLICK PATH:
Your Profile | Settings | Advanced User Details
How to Enable Debug Mode – Option 2 133
How to Enable Debug Mode – Option 3 134
Pretty Print
Debug Mode Enabled 137
Custom Formatters 138
CLICK PATH:
Chrome DevTools | Settings | Enable Custom Formatters
Programmatically Setting Breakpoints 139
debugger;
• package.json
• studentTile.test.js
Tasks:
1. Enable Debug Mode.
2. Use console.log() and breakpoints.
3. Discard unneeded changes.
4. Compare branches using GitLens.
20 Minutes
Lesson 2: Lightning Web Components 147
Course Delivery
Course Location Start Date … More fields
Number
Delivery_00000 [101] AWCA Server Tokyo, JP 2/15/2016 …
Delivery_00001 [101] AWCA Server San Francisco, CA 6/7/2016 …
Delivery_00002 [101] AWCA Server Paris, FR 3/22/2016 …
NOTE:
An Apex class with implicit (no sharing rules enforcement defined) or inherited sharing runs
as with sharing when used as a Lightning component controller.
Simple Object-Level and Field-Level Security 151
LWC Controller /
Where SOQL query in Apex Apex Apex
Aura Markup*
NOTE:
* The UI API can also be called from native mobile apps and custom web apps!
Expose an Apex Method to a Lightning Web Component 155
Wire Service
1 <template> studentBrowser.html
2 <c-student-browser-form></c-student-browser-form>
3 <lightning-tabset variant="scoped">
4 <lightning-tab label="Gallery">
5 <c-student-tiles student-list={students.data}></c-student-tiles>
6 </lightning-tab>
7 </lightning-tabset>
8 </template>
1 <template> studentTiles.html
2 <template for:each={studentList} for:item="student">
3 <c-student-tile student={student} key={student.Id}></c-student-tile>
4 </template>
5 </template>
Must be an Array or an iterable Object. If
undefined, a console error will occur.
* Options for Wire Service 160
QUESTION:
In the above example, what happens if we want to run some logic, such as
transforming the data, when the data returns?
Let’s wire a
FUNCTION!
* Wire an Apex Method to a JavaScript Function 161
NOTE:
If a reactive variable (prefixed with $) changes, wire service provisions new
data. A network request may not occur if the data is cached on the client.
* Exercise 2-7A: Working with Apex 163
Apex:
getStudents
@wire students
student-browser
custom component
@api studentList
student-tiles
custom component
@api student
student-tile
custom component
Exercise 2-7A: Work with Apex 164
Tasks:
1. Create an Apex Class and method 3. Output a set of Contacts as tiles.
that can be accessed by a
Lightning web component. 4. Explore Apex Logs.
2. Request data from the Salesforce
Platform.
25 minutes
Lightning Data Service 165
Database
User Interface API or Apex? 166
NOTE:
Apex allows you to work with a single record, but why bother!
lightning/uiRecordApi 167
getRecord()
Retrieves a record’s data, used uiRecordApi has plenty of
in wire statements other methods – and we'll
use some of them later!
getFieldValue()
Returns field data in its raw form
getFieldDisplayValue()
Returns field data formatted and localized, based on locale settings
NOTE:
Raw field values can also be retrieved using the syntax
record.data.fields.fieldname.value
* Wire a Function for Lightning Data Service (JavaScript) 168
wireSample.html
1 <template>
2 <lightning-card title="Wire Sample" icon-name="standard:contact">
3 <template if:true={recordId}>
4 <div class="slds-var-m-around_medium">
5 <p>{email}</p>
6 </div>
7 </template>
8 </lightning-card>
9 </template>
Wired Function Signatures 170
ldsUtils
Service component with reduceErrors() method.
Can handle different error object structures. Already in Base
metadata
errorPanel
Reusable component to display error messages.
NOTE:
Both of these components can be found in the lwc-recipes repo.
* Exercise 2-7B: Work with Lightning Data Service 172
student-detail
custom component
with valid hardcoded
Contact ID
student-detail
custom component
with invalid hardcoded
Contact ID
student-detail
custom component
with bad field name
Exercise 2-7B: Work with Lightning Data Service 173
Tasks:
1. Build the studentDetail
component.
2. Call getRecord() to fetch
information about a Contact.
3. Explore error handling.
20 minutes
Wire Service Summary 174
Whether you're decorating a property or a method, you can use the following.
Task Code sample
Use getRecord wire adapter @wire(getRecord) propertyOrMethod;
Use an Apex method (no DML) @wire(getInstructors) propertyOrMethod;
NOTE:
The @wire decorator is also used for PageReference which will be discussed later.
Lesson 2: Lightning Web Components 175
1 <template> app.html
2 <lightning-combobox label="Country" value={value} options={options}
3 onchange={handleChange}></lightning-combobox><br/>
4 Selected Country: {value}
5 </template>
• onfocus
• onblur
• onchange
app.html app.js
1 <lightning-combobox 1 value;
2 label="Country" 2
3 value={value} 3 handleChange(event) {
4 placeholder="Select Country" 4 this.value = event.detail.value;
5 options={options} 5 }
6 onchange={handleChange}>
7 </lightning-combobox>
NOTE:
Unlike Aura components or Visualforce pages, the properties are not bi-directional bound!
Implement an Icon Button 179
1 <template>
2 <lightning-button variant="brand" label="Download"
3 icon-name="utility:download" icon-position="left"
4 onclick={handleClick}></lightning-button>
5 </template>
1 handleClick(event) {
2 alert("Button was clicked!");
3 }
Theme <lightning-button> with Variant Options 180
Button Variants:
• base
• neutral (default)
1 <lightning-button variant="base"
2 label="Base" onclick={handleClick}> • brand
3 </lightning-button> • destructive
4
5 <lightning-button variant="brand" • inverse
6 label="Neutral" • success
7 onclick={handleClick}>
8 </lightning-button>
9
10 <lightning-button variant="destructive"
11 label="Neutral"
12 onclick={handleClick}>
13 </lightning-button>
Use the <lightning-layout> Grid System 181
Use the <lightning-layout> Grid System 182
1 <lightning-layout horizontal-align="space">
2 <lightning-layout-item flexibility="grow">
3 This is Column 1
4 </lightning-layout-item>
5 <lightning-layout-item flexibility="grow">
6 This is Column 2
7 </lightning-layout-item>
8 </lightning-layout>
Specify Columns with Relative Sizing 183
1 <template>
2 <lightning-layout class="slds-wrap">
3 <!-- row 1 -->
4 <lightning-layout-item class="slds-align-top" size="12">
5 Header
6 </lightning-layout-item>
7
8 <!-- Row 2 -->
9 <lightning-layout-item size="3" >Nav</lightning-layout-item>
10 <lightning-layout-item size="6" >Body</lightning-layout-item>
11 <lightning-layout-item size="3" >Aside</lightning-layout-item>
12
13 <!-- Row 3 -->
14 <lightning-layout-item size="12">Bottom Align</lightning-layout-item>
15 </lightning-layout>
16 </template>
Demo: Responsive Column Sizes 184
1 <template>
2 <lightning-layout multiple-rows>
3 <lightning-layout-item size="12">
4 Header</lightning-layout-item>
5 <lightning-layout-item size="6" small-device-size="6" medium-device-size="4">
6 Nav</lightning-layout-item>
7 <lightning-layout-item size="6" small-device-size="6" medium-device-size="4">
8 Body</lightning-layout-item>
9 <lightning-layout-item size="12" small-device-size="12" medium-device-size="4">
10 Aside</lightning-layout-item>
11 <lightning-layout-item size="12">
12 Footer</lightning-layout-item>
13 </lightning-layout>
14 </template>
You cannot have device specific size attributes for component without
specifying the `size` attribute, and the size attribute must come before
the device specific sizes.
JavaScript Template Literals 185
1 data.forEach(delivery => {
2 this.deliveries.push({
3 value: delivery.Id,
4 label: `${delivery.Start_Date__c} ${delivery.Location__c}
${delivery.Attendee_Count__c} students`
5 });
6 });
expression
* Exercise 2-8: Work with Base Lightning Components 186
Apex:
getInstructors
getDeliveriesByInstructor
@wire @wire
instructors deliveries
student-browser-form
custom component
onchange
student-browser
custom component
student-tiles
custom component
lightning-layout
lightning-layout-item
standard
components
Exercise 2-8: Work with Base Lightning Components 187
Tasks:
1. Use lightning-layout to define a two- 3. Create the Student Browser Form's
column, horizontal layout. instructor selector.
2. Create an Apex Class and methods 4. Create the Course Delivery selector
that can be accessed by a Lightning which is dynamically populated with
web component in order to read data for the selected instructor.
data from Salesforce Platform.
25 minutes
Lesson 2: Lightning Web Components 188
App Page
c-student-browser c-student-detail
c-student-browser-form
Custom event
c-student-tiles
c-student-tile
NOTE:
By default, custom events only propagate one level up. They do not bubble higher in the
component hierarchy.
* How Custom Events Work? (Child to Parent) 190
1 handleSampleEvent(event) { parent.js
2 alert(JSON.stringify(event.detail)); Must be named
3 } detail
Must start with on
lwcChild.html
1 <lightning-button label="Click Me" onclick={sendEvent}></lightning-button>
1 sendEvent() { lwcChild.js
2 const selectedEvent = new CustomEvent('sampleevent', {
3 detail: { author: "Rad", instructor: "EL Toro" }
4 });
5 Every letter must be
6
7 }
this.dispatchEvent(selectedEvent);
lowercase!
NOTE:
To preserve component encapsulation, send primitives or a copy of your object.
Declare an Event Listener Programmatically 191
eventListener.js
1 constructor() {
2 super();
3 this.template.addEventListener('sample', this.handleSample);
4 }
5
6 handleSample = (event) => {
7 // event handler logic here
8 };
App Page
c-student-browser c-student-detail
c-student-browser-form
c-student-tiles
c-student-tile
studentBrowser.html
1 <lightning-button variant="natural" label="Unselect Student"
2 onclick={handleUnselectStudent}></lightning-button>
3 <c-student-tiles student-list={students.data}
4 onstudentselected={handleNotify}></c-student-tiles>
1 handleUnselectStudent(){ studentBrowser.js
2 this.template.querySelector('c-student-tiles').unselectStudent();
3 }
A standard DOM API function that
returns the first element that
matches the component name.
• JavaScript does not allow you to extend more than one class at a time.
Mixin
Import lightning/
1 1 import { NavigationMixin } from 'lightning/navigation'; navigation
1 Import encodeDefaultFieldValues.
import { encodeDefaultFieldValues } from 'lightning/pageReferenceUtils';
student-browser-form
navigate
custom component
student-browser
custom component
@wire students
Apex:
getStudents
Exercise 2-9: Work with Events 201
Tasks:
1. Define two custom component 4. Use data passed by a component
events event in an Apex transaction
2. Raise both custom events
3. Handle both custom events
45 minutes
Lesson 2: Lightning Web Components 202
App Page
c-student-browser c-student-detail
c-student-browser-form
c-student-tiles
c-student-tile
Shadow DOM 204
Document Tree
c-student-tiles
1 <c-student-tiles> studentTiles.html
2 #shadow-root
3 <div>
c-student-tile
4 <p>Gallery</p>
5 </div>
6 <c-student-tile>
div 7 #shadow-root
8 <div>
9 <h1>{student.Name}</h1>
h1 10 </div>
11 </c-student-tile>
12 </c-student-tiles>
Shadow Boundary
NOTE:
The shadow tree encapsulate the elements in each Lightning web component and it affects how
we work with CSS, events and the DOM.
Define Event Propagation 207
c-student-tiles
bubbles (Boolean)
Indicates whether the event
c-student-tile can pass through the DOM
or not.
div
composed (Boolean)
h1
Indicates whether the event
can pass through the
Shadow Boundary
Shadow DOM or not.
Configure Bubbles and Composed 208
studentTile.js
1 const selectedEvent = new CustomEvent('studentselected', {
2 bubbles: true,
3 composed: true,
4 detail: { studentId: this.student.Id }
5 });
Event Retargeting 209
c-student-tiles
For bubbling events that cross
the shadow boundary, the value
c-student-tile
of Event.target changes to
match the scope of the listener.
Shadow Boundary
Event retargeting and scoped
CSS preserve shadow DOM
Event.target is h1
encapsulation
What is the LMS? 210
PUBLISH/SUBSCRIBE
App Page
c-student-browser c-student-detail
c-student-browser-form
LMS
c-student-tiles
c-student-tile
SelectedStudentChannel.messageChannel-meta.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
3 <apiVersion>52.0</apiVersion> Set to true to expose
4 <masterLabel>SelectedStudentChannel</masterLabel> to components in
5 <isExposed>true</isExposed> other namespaces.
6 <description>Lightning Message Channel for Selected Student.</description>
7 <lightningMessageFields>
8 <fieldName>studentId</fieldName>
9 <description>This is the record Id for the selected student.</description>
10 <fieldName>studentName</fieldName>
11 <description>The full name of the student.</description>
12 </lightningMessageFields>
lightningMessageFields
13 </LightningMessageChannel> specifies the fields that will
be part of the published
message.
NOTE:
This is the basic layout for a Lightning Message Channel.
Communication between Components through
* Lightning Message Service 214
student-tiles
custom component
Tasks:
1. Define and surface a new component in
Lightning App Builder.
2. Leverage LMS to use publish-subscribe
pattern to load a Contact record from the
Salesforce Platform.
20 minutes
Slide 217
MOU8 Replace "pub-sub" to "publish-subscribe" to remove the confusion with the Pub-Sub library we had before LMS
Microsoft Office User, 5/14/2021
Code Review 218
Not visible if no
studentTile selected
student-detail
custom component
lightning-button
navigate
lightning-card to standard
lightning-button record page
lightning-formatted-email
lightning-formatted-phone
Standard components
Lab Phase 1: Output Data from Lightning Data Service 223
Tasks:
1. Use the lightning-formatted-email component to
output the contact's Email.
2. Use the lightning-formatted-phone component to
output the contact's phone number.
3. Output the Contact description field underneath
the phone number.
60 minutes
Lab Phase 1: Output Data from Lightning Data Service
(Continued)
224
Tasks:
1. Add a button to the card that, when
pressed, uses the navigation service to
display the detail record page.
2. Hide the contents of studentDetail if
no student has been selected.
60 minutes
EXTRA CREDIT Reinforce your Skills with a Challenge 225
Delighted
with Data Challenge 2: Recent Worldwide Deliveries
Scenario
Create a component challenge_recentDeliveries that
retrieves the 3 most recent course deliveries into a
wired property deliveries. Use a method named
getRecentDeliveries in an Apex class named
CourseDeliveries.
1 mapMarkers = [{ deliveryListMap.js
2 location: {
3 'City': 'London',
4 'Country': 'UK',
5 },
6 description: 'London, UK, 5 sessions',
7 }]
Considerations
• No API key required.
• Hard limit: 10 Geocoded addresses
• Recommended max: 100 markers
Expose Properties to App Builder 229
deliveryListMap.js-meta.xml
…
1 <isExposed>true</isExposed>
2 <targets>
3 <target>lightning__AppPage</target>
4 </targets>
5 <targetConfigs>
6 <targetConfig targets="lightning__AppPage">
7 <property name="listView" label="List View"
8 type="String" datasource="visible,hidden" />
9 <property name="markersTitle" type="String"
10 label="List Title (if visible)” />
11 </targetConfig>
12 </targetConfigs>
…
Add <property> entries to the config file and decorate the properties with
@api to allow them to be configured at design time in Lightning App Builder.
Populate App Builder Picklists Dynamically (1 of 2) 230
… primaryCitySelector.js-meta.xml
1 <targetConfigs>
2 <targetConfig targets="lightning__AppPage">
3 <property name="city" label="Primary City"
4 type="String" datasource="apex://CityPicklist" />
5 </targetConfig>
6 </targetConfigs>
…
This is a component
property in App Builder,
and the option list is
dynamic!
Populate App Builder Picklists Dynamically (2 of 2) 231
CourseDeliveryLocations.cls
1 public with sharing class CourseDeliveryLocations {
2
Must be set in order
3 @AuraEnabled(cacheable=true) to use @wire to call
4 public static List<AggregateResult> getLocations() { the Apex method.
5
6 return [SELECT City__c, Country__c, COUNT(Id) numDeliveries
7 FROM Course_Delivery__c group by City__c, Country__c];
8 }
9 }
1 @wire(getLocations) locationComponent.js
2 wired_getLocations({ error, data }) {
3 this.mapMarkers = [];
4 if (data) {
5 data.forEach(loc => {
6 this.mapMarkers.push({location:{City: loc.City__c, Country: loc.Country__c}});
7 });
8 }
9 }
Create an Aura DeliveryListAction Component 233
1 <aura:component DeliveryListAction.cmp
2 implements="flexipage:availableForAllPageTypes,
3 force:lightningQuickAction" access="global">
4
5 <c:deliveryListMap />
6 </aura:component>
Set the name of the name of the interfaces you are implementing.
flexipage:availableForAllPageTypes
Makes your component available to Lightning App.
force:lightningQuickAction
Makes your component available to be used as a custom action in Lightning
Experience.
Create an Aura DeliveryListAction Component (Cont.) 234
1 <aura:component DeliveryListAction.cmp
2 implements="flexipage:availableForAllPageTypes,
3 force:lightningQuickAction" access="global">
4 <c:deliveryListMap />
5 </aura:component>
Quick Action
delivery-list-map
Filter List
custom
standard
component
component
Chatter Feed
standard
component
Exercise 3-1: Create a Lightning Component 236
Global Action with Aura
NOTE:
Currently, Global Actions only support Aura Components. To use a Lightning web component in
a global action, you must wrap it in an Aura component.
Exercise 3-1: Surface a Component in App Builder 237
deliveryDetailMap.js-meta.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <LightningComponentBundle
3 xmlns="http://soap.sforce.com/2006/04/metadata" fqn="map">
4 <apiVersion>52.0</apiVersion>
5 <isExposed>true</isExposed>
6 <targets>
7 <target>lightning__RecordPage</target>
8 </targets>
9 </LightningComponentBundle>
Add a property named recordId decorated with @api to access the current ID.
Configuring Form Factors 242
deliveryDetailMap.js-meta.xml
…
1 <isExposed>true</isExposed>
2 <targets>
3 <target>lightning__AppPage</target>
4 </targets>
5 <targetConfigs>
6 <targetConfig targets="lightning__AppPage">
7 <property name="prop1" label="Prop 1" type="String" />
8 <supportedFormFactors>
9 <supportedFormFactor type="Small" />
10 </supportedFormFactors>
11 </targetConfig>
12 </targetConfigs>
…
Add <supportedFormFactor> entries to the config file to define under which form
factors a component will be surfaced to a user. Small is phone, Large is desktop.
Quick Actions for Lightning Web Components 243
updateDeliveryLocation.js-
meta.xml
1 …
2 <isExposed>true</isExposed>
3 <targets>
4 <target>lightning__RecordAction</target>
5 </targets>
6 <targetConfigs>
7 <targetConfig targets="lightning__RecordAction">
8 <actionType>ScreenAction</actionType>
9 </targetConfig>
10 </targetConfigs>
11 …
A quick action allows us to open a component directly from a record page, or to execute
code silently.
Exercise 3-2: Build Components for Lightning 244
Experience Record Pages
Course Delivery Custom Record Page
Highlights Panel (Header and Right Sidebar)
Record delivery-detail-map
Detail new custom
standard component
component
Exercise 3-2: Build Components for Lightning
Experience Record Pages
245
Tasks:
1. Define a new Lightning web 3. Use Lightning App Builder to deploy
component for Lightning the component to a custom
Experience Record Pages. Lightning Record Page.
2. Retrieve Course Delivery record
data using the wire service.
25 minutes
Code Review 246
Tabs
Layout fully controlled by developer.
Cannot be customized by business users.
Surface Lightning Web Components in Salesforce 249
Mobile and Lightning Experience
layoutManager.js-meta.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <LightningComponentBundle
3 xmlns="http://soap.sforce.com/2006/04/metadata" fqn="map">
4 <apiVersion>52.0</apiVersion>
5 <isExposed>false</isExposed>
6 <targets>
7 <target>lightning__Tab</target>
8 </targets>
9 </LightningComponentBundle>
CLICK PATH:
Setup | User Interface | Tabs
Create a Two Column Layout in Code 252
1 <template> layoutManager.html
2 <lightning-layout>
3 <lightning-layout-item padding="around-small" size="8">
4 <c-student-browser></c-student-browser>
5 </lightning-layout-item>
6 <lightning-layout-item padding="around-small" size="4">
7 <c-student-detail></c-student-detail>
8 </lightning-layout-item>
9 </lightning-layout>
10 </template>
Add a Lightning Component Tab 253
to Salesforce Mobile Navigation
Lightning Component Tabs can be manually added to the Mobile Navigation
menu in the Setup interface.
CLICK PATH:
Setup | Apps | Mobile Apps | Salesforce Navigation
Add Lightning Component Tabs to the App 254
Launcher
CLICK PATH:
Setup | Apps | App Manager
Create a Container Component that Controls Layout 255
c-layout-manager
c-student-browser c-student-detail
c-student-browser-form
c-student-tiles
c-student-tile
Exercise 3-3: Surface a Component Lightning Experience 256
layout-manager
new custom component Custom component tab
student-detail
custom
component
student-browser
custom
component
Exercise 3-3: Surface a Component in Lightning
Experience
257
Tasks:
1. Define a top-level Lightning web 4. Define a Lightning Component tab.
component that defines the layout. 5. Surface a Lightning Component tab
2. Add a target to the metadata file. in a Lightning Experience App.
3. Upload a custom tab icon.
20 minutes
Lesson 3: Surface Lightning Web Components 258
NOTE:
Currently, Standard Actions Overrides only support Aura Components. To use a Lightning web
component to override Standard Actions, you must wrap it in an Aura component.
Wrap a Lightning Web Component in an Aura 260
Component
Override_View_CourseAttendee.cmp
1 <aura:component implements="lightning:actionOverride,
2 force:hasRecordId,force:hasSObjectName" access="global" > This is a
3 <c:courseAttendee recordId="{!v.recordId}" />
Lightning web
4 </aura:component>
component
Set the name of the name of the interfaces you are implementing.
lightning:actionOverride
Makes your component available for action overrides.
force:hasRecordId, force:hasSObjectName
Inject attribute values for recordId and sObjectName when possible.
Invoke Lightning Web Components from Aura 261
1 <aura:component
2 implements="lightning:actionOverride,force:hasRecordId">
3 <c:courseAttendee recordId="{!v.recordId}" />
4 </aura:component>
NOTE:
When referencing a child Lightning web component from an Aura component, we use the Aura
syntax and NOT:
<c-course-attendee record-id={recordId}></c-course-attendee>
Override a Standard Action 262
course-attendee
new custom
component
Override_View_CourseAttendee
new custom Aura component
Exercise 3-4: Override Standard Actions 264
Tasks:
1. Create a Custom Tab for the
Course_Attendee Custom Object
2. Define the Override Component
3. Register the Override
4. Test the Override
20 minutes
Lesson 3: Surface Lightning Web Components 265
• Open:
Exercises | main | default
• Right-click on aura
• Select:
SFDX: Create Aura App
• Enter a component name
Define and Browse to a Lightning App 267
1 <aura:application extends="force:slds">
2 <c:deliveryListMap />
3 </aura:application>
1 <aura:component
2 isTemplate="true"
3 extends="aura:template"> Title of browser tab
4
5 <aura:set attribute="title" value="My App"/>
6 <aura:set attribute="auraResetStyle" value=""/>
7 ...
8 </aura:component> Prevent a reset.css
from interfering with SLDS
1 <aura:application template="c:mytemplate">
2 ...
3 </aura:application>
Set Application Attributes via the Query String 269
1 <aura:application extends="force:slds">
2
3 <aura:attribute name="title" type="String" default="Title"/>
4 <aura:attribute name="message" type="String" default="Message"/>
5
6 <div class="panel panel-default">
7 <div class="panel-heading">{!v.title}</div>
8 <div class="panel-body">
9 {!v.message}
10 </div>
11 </div>
12
13 </aura:application>
URL PATH:
https://mydomain.lightning.force.com/c/
HelloWorld.app?title=Hello&message=World
Exercise 3-5: Create a Lightning App 270
Tasks
1. Define a Lightning Application
2. Invoke an Aura Component
3. Execute a Lightning Application from a Url.
4. Modify query string parameters and view the
impact.
15 minutes
Code Review 272
NOTE:
Lightning Components for Visualforce pages is the only way to surface Lightning web
components inside of Salesforce Classic.
Make your Components Available for Invocation from 275
Visualforce
Makes app available
for Lightning Out
1 <aura:application
2 extends="ltng:outApp">
3
4 <aura:dependency resource="c:deliveryListMap" />
5 <aura:dependency resource="lightning:badge" />
6
7 </aura:application>
Lists other components that will be needed by the
Lightning Out application so all dependencies can be
loaded once, at startup time, for efficiency.
NOTE:
A Lightning dependency app isn’t a normal Lightning app. It does not support templates,
and any markup in them won’t be rendered. Only use <aura:dependency> tags in the body.
Instantiate Lightning Web Components on a 276
Visualforce Page
1 <apex:page>
2
3 <!-- <script src="/lightning/lightning.out.js" /> -->
4 <apex:includeLightning/>
5
6 <!-- target div for placing component -->
7 <div id="mapDiv" />
8
9 <script>
10 // load the components into memory
11 $Lightning.use("c:vfDependency", function() {
12 // invoke the components and place on page
13 $Lightning.createComponent(
14 "c:deliveryListMap", // name of component to create
15 {listView:"hidden"}, // optional component props
16 "mapDiv" // HTML ID where to put component
17 );
18 });
19 </script>
20 </apex:page>
Exercise 3-6: Surface Components in 277
Visualforce Pages
DeliveryListVF
Visualforce Page
delivery-list-map
custom component
lightning-badge
standard component
Exercise 3-6: Surface Components in
Visualforce Pages
278
Tasks
1. Define an Application to load
components into memory.
2. Instantiate Lightning web
components on a Visualforce
page.
15 minutes
Lesson 3: Surface Lightning Web Components 279
Properties can
be exposed at
design time
NOTE:
Base lightning web components like <lightning-button> can be installed by running the
command npm install lightning-base-components
Base Components Recipes 283
• Use lightning-vertical-navigation
• Use lightning-datatable
• Implement Button Groups
• Build Responsive Layouts
<lightning-vertical-navigation> 288
1 <lightning-vertical-navigation selected-item="recent">
2 <lightning-vertical-navigation-section
3 label="Reports">
4 <lightning-vertical-navigation-item label="Recent"
5 name="recent" >
6 </lightning-vertical-navigation-item> Section
7 <lightning-vertical-navigation-item
8
9
label="All Reports" name="all" >
</lightning-vertical-navigation-item>
Collapsible
10 </lightning-vertical-navigation-section> overflow
11 <lightning-vertical-navigation-overflow>
12 <lightning-vertical-navigation-item
13 label="Regional Sales East" name="east" >
14 </lightning-vertical-navigation-item>
15 <lightning-vertical-navigation-item
16 label="Regional Sales West" name="west" >
17 </lightning-vertical-navigation-item>
18 </lightning-vertical-navigation-overflow>
19 </lightning-vertical-navigation>
Add Navigation Items to Sections and Overflows 290
NOTE:
Other sub-components lightning-vertical-navigation is used together with:
• lightning-vertical-navigation-item-badge
• lightning-vertical-navigation-item-icon
Handle Navigation Item Selection 291
1 if (data) { awNavigation.js
2 this.certifications = data.map(cert => ({
3 Id: cert.Id,
4 Name: cert.Name,
5 compoundKey: `certification|${cert.Id}|${cert.Name}`
6 }));
7}
Exercise 4-1: Implement a Vertical Navigation 293
aw-navigation
new custom
component
Exercise 4-1: Implement a Vertical Navigation 294
Tasks:
1. Create the Apex class to retrieve 5. Handle Navigation Selection .
certifications. 6. Deploy the Component.
2. Create the Navigation Component. 7. Modify the Layout.
3. Fetch the Certifications.
4. Dynamically Generate the Vertical
Navigation. 45 minutes
Lesson 4: Implement Navigation and Layouts 295
• Use lightning-vertical-navigation
• Use lightning-datatable
• Implement Button Groups
• Build Responsive Layouts
Introducing <lightning-datatable> 296
1 <template>
2 <div style="height: 300px;">
3 <lightning-datatable
4 key-field="id"
5 data={data}
6 columns={columns}>
7 </lightning-datatable>
8 </div>
9 </template>
NOTE:
Not supported on mobile devices.
Example <lightning-datatable> JavaScript Code 297
NOTE:
The checkbox column is displayed by default and it can be hidden by using the
hideCheckboxColumn attribute.
Grid Column Data Types 299
boolean Displays the icon utility:check if the value is true, and a blank value otherwise.
button Displays a button using lightning-button
currency Displays a currency using lightning-formatted-number
date Displays a date and time based on the locale using lightning-formatted-date-time.
See Displaying Date and Time Using Type Attributes.
email Displays an email address using lightning-formatted-email
location Displays a latitude and longitude of a location using lightning-formatted-
location
number Displays a number using lightning-formatted-number
percent Displays a percentage using lightning-formatted-number
phone Displays a phone number using lightning-formatted-phone
text Displays text using lightning-formatted-text
url Displays a URL using lightning-formatted-url
NOTE:
The data table formats the data cells of a column based on the type you specify for the column.
Each data type is associated with a base Lightning component.
Handle Row Selection 300
1 <lightning-datatable
2 key-field="contactId"
3 data={certifiedStudents}
4 columns={columnConfig}>
5 onrowselection={onRowSelection}
6 </lightning-datatable>
1 onRowSelection(evt) {
2 const numRowsSelected = evt.detail.selectedRows.length;
3 this.btnGroupDisabled = (numRowsSelected === 0);
4 }
* Exercise 4-2: Use <lightning-datatable> 301
aw-navigation
custom component
Exercise 4-2: Use <lightning-datatable> 302
Tasks:
1. Create the Apex class to retrieve
certifications.
2. Create the Datatable Component.
3. Retrieve and transform the data.
4. Define the Datatable Columns
35 minutes
5. Instantiate the Component.
Lesson 4: Navigation and Layouts 303
• Use lightning-vertical-navigation
• Use lightning-datatable
1 <lightning-button-group>
2 <lightning-button label="E-mail" data-btn-id="btn1" onclick={onCertActions}>
3 </lightning-button>
4 <lightning-button label="Send Cert." data-btn-id="btn2" onclick={onCertActions}>
5 </lightning-button>
6 <lightning-button label="Delete" data-btn-id="btn3" onclick={onCertActions}
7 variant="destructive">
8 </lightning-button> Custom attributes must
9 </lightning-button-group> be formatted as data-*
1 onCertActions (event) {
2 const btn = event.target.getAttribute('data-btn-id');
3 alert(`${btn} Clicked`);
4 }
NOTE:
The body of the component can contain lightning-button or lightning-button-menu.
Mutual Exclusivity Behavior 305
NOTE:
For getRecord, you can use getRecordNotifyChange instead of refreshApex.
Exercise 4-3: Implement <lightning-button-group> 308
aw-navigation certified-student-list
layout-manager custom component
custom component custom component
lightning-button-group
standard component
Tasks:
1. Add Buttons to the Certification 4. Handle the Delete Button Action.
List. 5. Refresh the Data after Delete.
2. Enable/Disable Buttons Based on
Grid Row Selection.
3. Define the Apex Method to Delete
Certifications. 25 minutes
EXTRA CREDIT Reinforce your Skills with a Challenge 310
Talented
with Tables Challenge 3: Create a Contact Directory
Scenario
Create a component challenge_contactDirectory that
uses a lightning-datatable to output all contact
names, email addresses, and phone numbers. Display
the component on the custom Home Page for the
Certification App.
30 min
Lesson 4: Navigation and Layouts 311
• Use lightning-vertical-navigation
• Use lightning-datatable
• Implement Button Groups
1. Go to:
https://developer.salesforce.com/docs/component-
library/bundle/lightning-layout
2. Click Example tab.
3. Select different example options.
4. Click Specification tab.
5. What happens when “Multiple Rows” is set to active?
Use the <lightning-layout> Grid System 313
Layout responds
dynamically to
available space to split
across multiple rows.
<lightning-layout class="slds-wrap">
<lightning-layout-item size="12">Header</lightning-layout-item>
<lightning-layout-item size="6" small-device-size="6"
medium-device-size="4">
Nav
</lightning-layout-item>
<lightning-layout-item size="6" small-device-size="6"
medium-device-size="4">
Body
</lightning-layout-item>
<lightning-layout-item size="12" small-device-size="12"
medium-device-size="4">
Aside
</lightning-layout-item>
<lightning-layout-item size="12">Footer</lightning-layout-item>
</lightning-layout>
You cannot have device specific size attributes for component without
specifying the size attribute, and the size attribute must come before
the device specific sizes.
Implement Responsive, Relative Column Sizing (SLDS 315
Markup)
1 <div class="slds-grid slds-wrap">
2 <header class="slds-col slds-size_1-of-1">Header</header>
3 <nav class="slds-col slds-size_6-of-12 slds-small-size_6-of-12
4 slds-medium-size_4-of-12">
5 Nav
6 </nav>
7 <div class="slds-col
8 slds-size_6-of-12 slds-small-size_6-of-12
9 slds-medium-size_4-of-12 ">
10 Body
11 </div>
12 <aside class="slds-col slds-size_12-of-12 slds-small-size_6-of-12
13 slds-medium-size_4-of-12 ">
14 Aside
15 </aside>
16 <footer
17 class="slds-col slds-size_1-of-1">Footer</footer>
18 </div>
Conditional Column Reordering – What is it? 316
1 <template> layoutManager.html
2 …
3 <lightning-layout-item class="slds-order_1"
4 padding="around-small" size="12" small-device-size="12"
5 medium-device-size="3" large-device-size="2">
6 <c-aw-navigation onnavitemselected={handleNavItemSelected}>
7 </c-aw-navigation> slds-order_x
8
classes set the
</lightning-layout-item>
9 <template if:true={studentBrowserView}>
10
11
<lightning-layout-item class="slds-order_3 slds-medium-order_2"
padding="around-small" size="12" small-device-size="12" order for
12
13
medium-device-size="5" large-device-size="7">
<c-student-browser></c-student-browser>
different screen
14 </lightning-layout-item> sizes.
15 <lightning-layout-item class="slds-order_2 slds-medium-order_3"
16 padding="around-small" size="12" small-device-size="12"
17 medium-device-size="4" large-device-size="3">
18 <c-student-detail></c-student-detail>
19 </lightning-layout-item>
20 </template>
21 …
22 </template>
Create Independently Scrolling Regions 319
1 <template> studentBrowser.html
2 …
3 <div class="slds-scrollable scrollerSize" >
4 <c-student-tiles student-list={students} onstudentselected={handleNotify}>
5 </c-student-tiles>
6 </div>
7 …
8 </template>
studentBrowser.css
1 .scrollerSize {
2 height:300px;
3}
NOTE:
slds-scrollable is Desktop Only.
Exercise 4-4: Create a Responsive Layout 320
Wide View
Narrow View
scrollbar
Exercise 4-4: Create a Responsive Layout 321
Tasks:
1. Configure a responsive layout.
2. Enable scrolling.
15 minutes
Lesson Summary 322
Table rows become stacked groups, and fields (for example, Title) are
optionally hidden.
1 <template>
2 <table class="slds-table slds-table_bordered slds-max-medium-table_stacked">
3 <thead>
4 <tr class="slds-text-heading_label">
5 <template for:each={columnConfig} for:item="col">
6 <th key={col.fieldName} scope="col" class={col.class}>
7 <span class="slds-truncate">{col.label}</span></th>
8 </template>
9 </tr>
10 </thead>
11 <tbody>
12 …
13 </template>
NOTE:
Apply slds-max-medium-table_stacked to modify table layout by stacking
cells to accommodate smaller viewpoints.
Apply a Media Query for Hidden CSS 328
Media Query
Media queries can be used to hide elements depending on the screen size.
Annotate either the getter or the setter with @api, but not both.
It’s a best practice to annotate the getter.
1 rows;
2 @api
3 get rowData() {
4 return this.rows;
5 }
6 set rowData(value) {
7 if (typeof value !== "undefined") {
8 this.rows = this.reformatRows(value,this.columnConfig);
9 }
10 }
[{ Id: 1, [{ pk: 1,
Name: "John Doe", data:
Order of items in data[] is consistent
Title: "Tech", [{ and matches columnConfig
Email: "j@doe.com" label: "Name",
}] value: "John Doe",
reformatRows() class: "",
isEmail: false, isOther: true,
columnConfig = [ type: undefined
{ },{
fieldName:"Name", label: "Title",
label: "Name" value: "Tech",
}, class: "hiddenOnMobile",
{ isEmail:false, isOther:true,
fieldName:"Title", type: undefined
label: "Title", }, {
hiddenOnMobile: true label: "E-Mail",
}, value: "j@doe.com",
{ class: "",
fieldName:"Email", isEmail: true, isOther: false,
label: "E-Mail", type: "email"
type: "email" }]
}]; }]
Implement Data Pagination 331
Narrow View
@api columnConfig
@api rowData
student-browser responsive-datatable
custom component new custom
component
Title field hidden in
narrow view
Exercise 5-1: Create a Responsive Datatable 333
Tasks:
1. Install a component. 5. Deploy the component
2. Re-raise DOM events. 6. Hide “Hidden” detail fields
3. Highlight the selected row 7. Open an editor modal on double-
4. Use a custom setter to reformat click
row data
40 minutes
Lesson 5: Advanced Components 334
1 updateSelectedStudent(studentId) {
2 const grid = this.template.querySelector('c-data-grid-table');
3 const gallery = this.template.querySelector('c-student-tiles');
4 if (gallery) {
5 gallery.setSelectedStudent(studentId);
6 }
7 if (grid) {
8 grid.setSelectedRecord(studentId);
9 }
10 }
1 @api setSelectedRecord(recordId) {
2 const mySelector = `tr[data-pk='${recordId}']`;
3 const selectedRow = this.template.querySelector(mySelector);
4 if (selectedRow) {
5 this.highlightSelectedRow(selectedRow);
6 }
7 }
Exercise 5-2: Use Custom Events and Public Methods 336
student-browser: student-detail:
handle rowclick handle studentChange via LMS
• publish LMS - reloadRecord
• call setSelected public method in responsiveDatatable
• call setSelectedStudent public method in studentTiles
responsive-datatable
custom component
Exercise 5-2: Use Public Methods 337
Update your solution to keep the grid and gallery tabs in sync by
calling public methods.
Tasks:
1. Define a rowclick event.
2. Define two public methods on
components.
3. Invoke two public methods on
components.
4. Discuss deferred instantiation. 25 minutes
Lesson 5: Advanced Components 338
Service Component
namedUtils.js
1 function alertMessage(msgToAlert) {
2 alert(msgToAlert); A module can also
3 } export named
4 function logMessage(msgToLog) {
5 console.log(msgToLog);
functions, variables,
6 } and classes.
7 export {alertMessage, logMessage};
Same
name myApp2.js The module that
required imports the functions
1 import {alertMessage, logMessage}
2 from 'c/namedUtils'; or variables must use
3 alertMessage('Hello user!'); the exported names.
4 logMessage('Hello console!');
Examples of Default and Named Exports 342
TOAST MESSAGE
1 <template>
2 <lightning-button
3 label="Show Toast"
4 onclick={btnClick}>
5 </lightning-button>
6 </template>
connectedCallback()
call Utils.showToast static method utils custom service component calls
layout-manager ShowToastEvent standard event
custom component
Exercise 5-3: Use Toasts and Service Components 347
Tasks:
1. Create the Service Component.
2. Define a Function to Show Toast
Notifications.
3. Display a Toast Notification at
Startup.
4. Refactor some code. 35 minutes
Lesson 5: Advanced Components 348
slotWrapper.html slotDemo.html
1 <template> 1 <template>
2 <c-slot-demo> invokes 2 <h1>Add content to slot</h1>
<p>Content from parent</p> 3 <div>
3 <slot></slot>
4
4 </c-slot-demo> </div>
5
5 </template> 6 </template>
namedSlots.html
1 <template>
2 <p>First Name: <slot name="firstName">Default first name</slot></p> Define named
3 <p>Last Name: <slot name="lastName">Default last name</slot></p> slots
4 <p>Description: <slot>Default description</slot></p>
5 </template>
1 <template> usesNamedSlots.html
2 <c-named-slots>
3 <span slot="firstName">El</span>
4 <span slot="lastName">Toro</span> Pass markup
5 <span>Global Master Instructor</span> into slots
6 </c-named-slots>
7 </template>
1 <c-named-slots> usesNamedSlots.html
2 <p>First Name:
3 <slot name="firstName"><span slot="firstName">El</span></slot></p>
Rendered
4 <p>Last Name:
5 <slot name="lastName"><span slot="lastName">Toro</span></slot></p> output
6 <p>Description:
7 <slot><span>Global Master Instructor</span></slot></p>
8 </c-named-slots>
Modals 352
Call modal.hide
public method
Exercise 5-4: Implement Modals using Slots 354
Tasks:
1. Install the Modal Component. 5. Show a Notification when a Feature
2. Define a Function to Show Modal is not Available.
Notifications.
3. Handle the Custom Event.
4. Invoke the Modal in the Root
Component. 30 minutes
Lesson 5: Advanced Components 355
• Localization
• Renderers and Third-Party JS
Localize Content 356
CLICK PATH:
Setup | User Interface | Custom Labels
Translation Workbench 359
When the assigned users log in to Lightning Experience and edit a custom
label, they’ll be presented with an option to translate that label into their
assigned languages, as illustrated by the figure.
Programmatically Access Labels 361
Syntax:
import labelName from '@salesforce/label/labelReference';
Example:
myLabels.js
1 import LABEL1 from '@salesforce/label/c.label1';
2 import LABEL2 from '@salesforce/label/c.label2'; Import labels
3 import LABEL3 from '@salesforce/label/c.label3';
4
5 export default {
6 LABEL1, Export labels as object
7 LABEL2,
8 LABEL3
9 }
useLabels.js
1 import { LightningElement } from 'lwc';
2 import labels from './myLabels'; Import object
3
4 export default class UseLabels extends LightningElement {
5 labels = labels;
6 } Make object available to HTML template as
{labels.LABEL1}, {labels.LABEL2}, {labels.LABEL3}
Use @salesforce/i18n Scoped Module 363
Locale Setting:
English (United States)
1 <template>
2 <lightning-formatted-number $5000.00
3 value="5000"
4 format-style="currency"
5 currency-code="USD">
6 </lightning-formatted-number> Locale Setting:
7 </template> French (France)
5000,00 $US
NOTE:
Currencies default to 2 decimal places.
Exercise 5-5: Localize Content 366
c-aw-navigation c-layout-manager
custom component custom component
c-certified-student-list
custom component
Exercise 5-5: Localize Content 367
Tasks:
1. Define a label.
2. Deploy the label.
3. Translate the label.
4. Verify that the label is output for
Spanish-speaking users.
15 minutes
Lesson 5: Advanced Components 368
loadScript(this, resourceName);
NOTE:
You cannot load JavaScript resources from a third-party site, even a CSP Trusted Site.
Use an External Style Sheet with loadStyle 371
loadStyle(this, resourceName);
NOTE:
External style sheets allow you to share styles across components despite the Shadow DOM.
Work with External APIs 372
The approach you select will impact what setup changes you must make.
1 fetch(apiURL)
2 .then((result) => {
3 // fetch may not throw an error if the request fails.
4 // So, let’s check the OK property.
5 if (!result.ok) {
6 this.error = response;
7 }
8 return result.json(); The Fetch API is currently not
9 } polyfilled for usage in IE11.
10 .then((jsonResponse) => {
11 this.someData = jsonResponse;
12 } Use XMLHttpRequest instead
.catch(error => {
13
this.error = error;
in that case.
14
15 this.books = undefined;
16 });
Pass Apex Data into ChartJS using Promises 374
1 loadScript(this, chartjs)
.then(getCertPopularity)
The name you gave the
2
3 .then((result) => { Apex method in the import
4 const certData = result; statement above.
5 const certLabels = [];
6 const certCounts= [];
7 for (let i=0; i < certData.length; i++) {
8 certLabels.push(certData[i].Name);
9 certCounts.push(certData[i].Number_of_Certified_Professionals__c);
10 }
Lightning Locker 375
• Available in the
Component Library
• The SecureWindow,
SecureDocument, and
SecureElement wrappers
prevent use of APIs that are
labeled "Not Supported".
NOTE:
To prevent security risks, you can’t use third-party web components on the Salesforce platform.
Locker and DOM Access Containment 378
A component can only traverse the DOM and access elements that it created.
Lightning web components cannot use the window or document
global properties to query for DOM elements.
domAccess.html
1 <template>
2 <div class="c1">Testing querySelector</div><BR />
3 <lightning-button onclick={go} label="Go"></lightning-button>
4 </template>
domAccess.js
1 go(){
2 alert(this.template.querySelector('.c1')); //SecureElement (div)
3 alert(document.querySelector('.c1')); //null
4 }
Exercise 5-6: Renderers and Third-Party JS 379
c-aw-navigation c-layout-manager
custom component custom component
c-cert-popularity
custom component
Exercise 5-6: Renderers and Third-Party JS 380
Tasks:
1. Create a Static Resource. 6. Deploy the Component.
2. Create an Apex class. 7. Render the Chart.
3. Create the Component Markup.
4. Create the CSS File.
5. Create the JS Controller.
35 minutes
Lesson 5 Summary 381
1. How can you execute custom 4. List two ways to reuse code in
logic when the value of a public Lightning web components.
property changes?
5. Every Lightning web component
2. List three ways a parent has an unnamed slot
component can communicate (true/false).
with a child component.
6. How does Salesforce determine
3. If you allowlist a domain in CSP the locale for logged in users?
Trusted Sites, you can load
resources from that domain
using the <script> tag
(true/false).
EXTRA CREDIT Reinforce your Skills with a Challenge 383
Awesome
with APIs Challenge 4: Website Visits per Month
Scenario
Create a component challenge_lineChart that uses a
chartJS to output a line chart using data from an
external URL that can be configured at design time in
App Builder.
40 min
Lesson 6:
Work with Data
Lesson 6 : Work with Data 385
• Implement Forms
• Implement Forms with Custom Controls
• Validate Input Data
• View and Edit Salesforce Records
• Wait for Server Requests to Complete
Lightning-record-form vs Lightning-record-edit-form vs 386
Lightning-record-view-form - a Feature Comparison
Create Records
Edit Records
View Records
Read-Only Mode
Layout Types
Multi Column Layout
Custom Layout for
Fields
Custom Rendering of
Record Data
<lightning-record-form> 387
1 <lightning-record-form
2 record-id={recordId}
3 object-api-name="Account"
4 fields={fields}
5 columns="1"
6 mode="view">
7 </lightning-record-form>
<lightning-record-edit-form> 388
1 <lightning-record-view-form
2 record-id={recordId}
3 object-api-name="My_Contact__c">
4 <div class="slds-box">
5 <lightning-output-field field-name="Name">
6 </lightning-output-field>
7 <lightning-output-field field-name="Email__c">
8 </lightning-output-field>
9 </div>
10 </lightning-record-view-form>
<lightning-output-field> 390
1 <lightning-record-view-form
2 record-id="001XXXXXXXXXXXXXXX"
3 object-api-name="Contact">
4 <div class="slds-box slds-theme_default">
5 <lightning-output-field field-name="Name">
6 </lightning-output-field>
7 <lightning-output-field field-name="Phone">
8 </lightning-output-field>
9 <lightning-output-field field-name="Email">
10 </lightning-output-field>
11 </div>
12 </lightning-record-view-form>
NOTE:
In orgs that support multiple languages, lightning-output-field automatically shows the
translated labels and picklist values.
Exercise 6-1: Work with Data 391
Tasks:
1. Create the TripReportForm
Component.
2. Define Form Fields
3. Setup the Controller.
4. Deploy the Component.
25 minutes
Lesson 6 : Work with Data 393
• Implement Forms
1 <template>
2 <lightning-slider
3 label="Volume"
4 step="10"
5 value="10"
6 onchange={handleChange}>
7 </lightning-slider>
8 </template>
getObjectInfo()
Get metadata about a specific object. Includes metadata describing
fields, child relationships, record type, and theme.
getPicklistValues()
Get the picklist values for a specified field.
getPicklistValuesByRecordType()
Get the values for every picklist of a specified record type.
* Get Picklist Values without Apex using UiObjectInfoApi 398
1 saveTripReport() {
2 const fieldsToSave = {}
fieldsToSave[FIELD_DATE.fieldApiName] = this.dateVisited;
3
fieldsToSave[FIELD_INSTRUCTOR.fieldApiName] = this.instructorId;
When creating, send
4
5 fieldsToSave[FIELD_RATING.fieldApiName] = this.rating; the object API name.
6 …
7 if (!this.recordId) {
8 const recordInput = { fields:fieldsToSave, apiName: OBJECT_TRIP_REPORT.objectApiName};
9 createRecord(recordInput)
10 .then(tripReport => { this.recordId = tripReport.id; } After creating, store
11 .catch(…) the new recordId.
12 } else {
13 fieldsToSave[FIELD_ID.fieldApiName] = this.recordId;
14 const recordInput = { fields:fieldsToSave}
15 updateRecord(recordInput)
16 .then(…)
17 .catch(…) When updating,
18 } send the recordId.
19 }
Compare Forms 401
TripReportForm TripReportFormAdvanced
Exercise 6-2: Implement a Form using Custom Controls 402
c-aw-navigation c-trip-report-form-advanced
custom component custom component
lightning-combobox
lightning-input
lightning-input
lightning-radio-group
lightning-slider
lightning-input-
rich-text
Exercise 6-2: Implement a Form using Custom Controls 403
Tasks:
1. Create the tripReportFormAdvanced 6. Define a Slider Control.
Component. 7. Define a Rich Text Field.
2. Setup the form shell. 8. Add Save and Cancel Buttons.
3. Implement the Instructor Selection 9. Save the record using Lighting Data
Box. Service.
4. Define Additional Form Fields. 10. Deploy the Component.
5. Implement a Radio Group. 40 minutes
Lesson 6 : Work with Data 404
• Implement Forms
• Implement Forms with Custom Controls
1 <template>
2 <lightning-input label="First name"
3 placeholder="First name"
4 required>
5 </lightning-input>
6 <lightning-input label="Last name"
7 placeholder="Last name"
8 required>
9 </lightning-input>
10 <lightning-button type="submit"
11 label="Submit"
12 onclick={handleClick}>
13 </lightning-button>
14 </template>
Validation Rules and Strings 407
• step-mismatch
• too-long
NOTE:
Check other input components’ specification to see
which messages they support.
Programmatically Determine Field Validity 408
1 validateFields() {
2 const fields = Array.from(this.template.querySelectorAll(
3 '.validateMe'));
4 return fields.every((currentField) => currentField.checkValidity());
5 }
Code Highlights
Array.from() Static method that converts a NodeList into an Array.
querySelectorAll() Retrieve a NodeList of DOM elements.
validateMe CSS class added to all components we will inspect. Your strategy may differ!
every() Instance method of Array that checks if every element passes a test.
Public method that can return false for various reasons, including valueMissing,
checkValidity()
tooLong, tooShort. Behavior depends on attributes set on input field in markup.
Not used here. Similar to checkValidity() but forces components to display
reportValidity()
message if invalid.
Exercise 6-3: Validate Input Data 409
c-trip-report-form-advanced
custom component
onblur event
handlers
Disabled unless
all fields valid
Exercise 6-3: Validate Input Data 410
Add onblur handlers that fire a function that loops through all
fields that need to be examined and calls checkValidity() to
make sure that the form is valid before allowing a submission.
Tasks:
1. Prepare the component for
validation.
2. Define a Field Validation Function.
3. Define the onBlur function.
20 minutes
Lesson 6 : Work with Data 411
• Implement Forms
• Implement Forms with Custom Controls
• Validate Input Data
responsive-datatable
custom component
trip-report-form-advanced
custom component
Exercise 6-4: View and Edit Salesforce Records 414
Tasks:
1. Create the TripReport Browser. 5. Use lightning-record-view-form to
2. Enable Context Switching. Display Record Details.
3. Enable the Cancel Button.
4. Load Data into the Form when a
Grid Row is double-clicked.
35 minutes
Lesson 6 : Work with Data 415
• Implement Forms
• Implement Forms with Custom Controls
• Validate Input Data
• View and Edit Salesforce Records
1 <template>
2 <lightning-spinner
3 variant="brand"
4 size="large"
5 alternative-text="Loading...">
6 </lightning-spinner>
7 </template>
Placement of <lightning-spinner> 417
The markup for the spinner is at the top of <c-layout-manager> and the
value of the loading property determines whether or not the spinner is
displayed.
layoutManager.html
1 <template if:true={loading}>
2 <lightning-spinner
3 alternative-text="Loading">
4 </lightning-spinner>
5 </template>
Event Flow for Spinner Show/Hide 418
studentBrowser.js
Fires in handleFilterChange 1 this.dispatchEvent(new CustomEvent(
2 'loading', {bubbles:true, composed:true}
3 ));
4 …
Fires in wired_getStudents 5 this.dispatchEvent(new CustomEvent(
6 'doneloading', {bubbles:true, composed:true}
7 ));
layoutManager.html
1 <span onshowmodal={handleShowModal}
onloading={handleLoading}
Declarative handlers on 2
3 ondoneloading={handleDoneLoading}>
<span> at app root …
4
5 </span>
layoutManager.js
Listeners toggle 1 handleLoading() { this.loading = true;}
this.loading 2 handleDoneLoading() { this.loading = false;}
lightning-spinner for a Section 419
Use the class slds-is-relative to restrict the space taken by the spinner.
This works well with a lightning-card. The code below is an example and is not
part of your exercise.
certifiedStudentList.html
1 <lightning-card title={certificationName}>
2 <!-- button group omitted for brevity -->
3 <div class="slds-is-relative">
4 <lightning-spinner alternative-text="Loading"
5 variant="brand"></lightning-spinner>
6 <lightning-datatable
7 key-field="contactId"
8 data={certifiedStudents}
9 columns={columnConfig}
10 onrowselection={onRowSelection}>
11 </lightning-datatable>
12 </div>
13 </lightning-card>
Exercise 6-5: Wait for Server Requests to Complete 420
Tasks:
1. Define the Markup.
2. Raise the Events.
3. Handle the Events.
20 minutes
Lesson 6 Summary 422
force:source:push force:source:deploy
Local Files Org Local Files Org
force:source:pull force:source:retrieve
package.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
This example pulls Apex <Package
Classes, Lightning xmlns="http://soap.sforce.com/2006/04/metadata">
Components and Static <types>
<members>*</members>
Resources. <name>ApexClass</name>
</types>
<types>
The default package.xml <members>*</members>
from VS Code will include <name>LightningComponentBundle</name>
</types>
much more. <types>
<members>*</members>
<name>StaticResource</name>
</types>
<version>52.0</version>
</Package>
NOTE:
AuraDefinitionBundle is for Aura components whereas LightningComponentBundle
is for Lightning web components.
Package.xml Generator Extension 429
• It generates
package.xml for you
Org Browser 430
Retrieve your Base using: Create yours using: Include these steps:
• Package.xml • ETCopyData 1. Create org with shape
• Org Browser • force:data:tree:export / import 2. Push metadata
• Unmanaged • Datafall 3. Assign permission set
Package • Hard-coded Apex Classes 4. Create data
Retrieve Your Metadata 432
• Your CreateOrg script has a commented-out command that you can use.
How do we Deploy Back to Another Org? 434
• Running sfdx
force:source:deploy
Exercise 7-1: Deploy a Component to a Dev Hub 435
Tasks:
1. Set the Default Org to the Dev Hub. 5. Deploy a Component using
2. Verify that the Component is Not package.xml
Available in the Dev Hub. 6. Review the Concepts
3. Deploy Fields Individually.
4. Generate a package.xml
15 minutes
EXTRA CREDIT Reinforce your Skills with a Challenge 436
Fantastic
with Forms Challenge 5: Delivery Location Editor
Scenario
Create a component challenge_courseDeliveryForm
that uses a lightning-record-form to allow users to edit
the City and Country fields on the Course Delivery
Object. Place the component below the
deliveryDetailMap component on the custom Course
Delivery record page you created earlier.
NOTE:
Aura components with slow user interface are a great option for migration.
* Map Aura and Lightning Web Component Bundle 439
Aura
1 <aura:attribute name="recordId" type="Id" />
2 <aura:attribute name="property" type="Property__c" access="private" />
LWC
1 import { LightningElement, api, track } from 'lwc';
2 export default class PropertySummary extends LightningElement {
3 @api recordId;
4 @track property;
5 ...
6}
NOTE:
Aura attributes get converted to JavaScript properties.
Aura CSS Becomes Standard CSS 441
Aura LWC
1 .THIS .truncate { 1 .truncate {
2 width: 100%; 2 width: 100%;
3 white-space: nowrap; 3 white-space: nowrap;
4 overflow: hidden; 4 overflow: hidden;
5 text-overflow: ellipsis; 5 text-overflow:ellipsis;
6 } 6}
NOTE:
- LWC encapsulates the elements using a Shadow DOM.
- CSS Styles defined in a component ONLY APPLY to that component.
- They do not leak, as they did in Aura.
ES6 Format 442
LWC
1 import { LightningElement, api, track } from 'lwc';
2 export default class PropertySummary extends LightningElement {
3
4 @api recordId;
5 @track property;
6 ...
7 }
Access an ES6 Module in an Aura Component 443
1 ({ Aura (controller)
2 myFunction: function(component, event, helper) {
3 console.log(component.find('utils').isFunction(...));
4 }
5 })
NOTE:
• utils.js is a LWC service component with code in ES6 format.
• We added an aura:id so that we can get a reference to the module in JavaScript code.
Use Third-Party JavaScript Libraries 444
Aura
1 <ltng:require scripts="{!$Resource.resourceName}"
2 afterScriptsLoaded="{!c.afterScriptsLoaded}" />
LWC
1 import resourceName from
2 '@salesforce/resourceUrl/resourceName';
NOTE:
To use a third-party JavaScript library in an Aura component or a Lightning web
component, you must upload the library as a static resource.
Composed Components 445
NOTE:
In Lightning web components, the data binding for property values is ONE WAY.
If the property value changes in the owner component, the updated value
propagates to the child component. The reverse is not true.
Component Events Become DOM Events 446
catchAndRelease.js
1 import { LightningElement } from 'lwc';
2 export default class CatchAndRelease extends LightningElement {
3 handleFireMyToast(evt) {
4 const eventName = 'notification';
5 const event = new CustomEvent(eventName, {
6 detail: { message: 'See you on the other side.' }
7 });
8 this.dispatchEvent(event);
9 }
10 }
catchAndReleaseWrapper.cmp
1 <aura:component implements="force:appHostable">
2 <c:catchAndRelease onnotification="{!c.handleCustomEvent}"/>
3 </aura:component>
Toggle CSS classes 447
In Aura, we use the following Aura utility methods to add and remove CSS
classes: $A.Util.addClass, $A.Util.removeClass $A.Util.toggleClass
In LWC, use querySelector and call the native classList.add / remove / toggle
The example below comes from the modal.
modal.js
1 const CSS_CLASS = 'modal-hidden';
2 …
3 @api show() {
4 const outerDivEl = this.template.querySelector('div');
5 outerDivEl.classList.remove(CSS_CLASS);
6 }
7
8 @api hide() {
9 const outerDivEl = this.template.querySelector('div');
10 outerDivEl.classList.add(CSS_CLASS);
11 }
Expressions in Aura vs Expressions in LWC 448
In aura .cmp files, you can have an expression in your markup, like:
In LWC you cannot put logic in the html. So, do something like:
<template if:true={studentBrowserView}>
get studentBrowserView() {
return (this.viewMode === 'students');
}
Aura:id and component.find() vs data-id and 449
querySelector()
c-student-detail custom
component
lightning-tabset
lightning-tab
lightning-combobox
lightning-input-rich-text
Contact lightning-button
Tasks:
1. Define component iii. A lighting-input-rich-text field that is
bound to the InstructorNotes__c field.
studentNoteEditor that uses:
iv. A button to save instructor notes.
i. A select box populated with related
Course_Attendee__c records. v. On save, output a success message
using a Toast message.
ii. LDS to load the InstructorNotes__c
data.
75 minutes
Lab Phase 2: Lightning Data Service CRUD Operations
(CONTINUED)
454
Tasks:
1. Modify the studentDetail.html file tab to display a message indicating
to include a tab panel with two that the student has not registered
tabs labeled HISTORY and EDIT for any courses.
NOTES. If the student has no 2. In the Edit Notes tab, invoke the
history, hide the EDIT NOTES tab studentNoteEditor component.
and use the body of the HISTORY 75 minutes
Lab Phase 3 (optional)
Read and Output Dynamic Data
Lab Phase 3: Read and Output Dynamic Data 456
c-student-detail custom
component lightning-button
lightning-formatted-email
lightning-formatted-phone
lightning-formatted-text
c-student-note-editor
custom component
lightning-select
lightning-tabset
lightning-tab
lightning-input-rich-text
lightning-tile
20 minutes
Certification 458
Superbadge
Lightning Web Components Specialist
JavaScript Developer I
Multiple-Choice Exam
NOTE:
The JavaScript Developer I exam does not have questions about Lightning Web Components.
Thanks for Attending!
Your opinion matters, and we want to hear from you. Navigate to the
Survey provided by your instructor to give us your feedback.
What’s Next?
LEARN ALL THE SKILLS YOU NEED
Build on your skills with self-paced learning or another expert-led class.
https://sfdc.co/learnsalesforce