Mobile Offline Developer
Mobile Offline Developer
Mobile Offline Developer
Guide
Version 60.0, Spring ’24
@salesforcedocs
Last updated: February 16, 2024
© Copyright 2000–2024 Salesforce, Inc. All rights reserved. Salesforce is a registered trademark of Salesforce, Inc., as are other
names and marks. Other marks appearing herein may be trademarks of their respective owners.
CONTENTS
Chapter 1: Mobile App Development with Lightning Web Components and LWC
Offline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
About This Developer Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
LWC Offline Enabled Apps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Learn Lightning Web Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Learn Lightning Web Components with Trailhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Learn Lightning Web Components with Documentation . . . . . . . . . . . . . . . . . . . . . . . . 4
1
Mobile App Development with Lightning Web Components About This Developer Guide
and LWC Offline
Note: Your organization must purchase and license Salesforce Mobile App Plus in order to use Mobile Offline. Contact your
Salesforce sales rep for more information.
SEE ALSO:
Salesforce Help: Salesforce Mobile App Plus
GitHub: Offline App Developer Starter Kit
IN THIS SECTION:
Learn Lightning Web Components with Trailhead
If you’re not already an experienced LWC developer, the best way to learn Lightning web components is with the extensive collection
of lessons and projects on Trailhead.
Learn Lightning Web Components with Documentation
Use the Lightning Web Component Developer Guide to understand the Lightning Web Components framework and how to use it
with Salesforce.
2
Mobile App Development with Lightning Web Components Learn Lightning Web Components with Trailhead
and LWC Offline
Note: Most LWC modules and projects are general purpose, rather than specific to a particular mobile app. For setting up to
specifically work with Lightning web components and your specific mobile app, such as the Field Service mobile app, follow the
steps provided in Set Up Your Development Environment on page 155.
• Quick Start: Lightning Web Components
• Set Up Your Salesforce Mobile Developer Tools for Lightning Web Components
• Set Up Your Lightning Web Components Developer Tools
3
Mobile App Development with Lightning Web Components Learn Lightning Web Components with Documentation
and LWC Offline
4
CHAPTER 2 Create Mobile-Ready Components
In this chapter ... Build components that perform well across mobile experiences. These guidelines are best practices, not
universal rules. Consider them carefully, but don’t be afraid to go your own way if there are compelling
• Understand Mobile reasons in specific situations.
Development for
Lightning Web
Components
• Use Built-In Mobile
Tools and Features
• Minimize Bandwidth
Usage
• Create Responsive
Layouts
• Follow Accessible
Mobile Design
Guidelines
• Disable
Pull-to-Refresh in the
Salesforce Mobile
App
5
Create Mobile-Ready Components Understand Mobile Development for Lightning Web
Components
• Set Up Your Salesforce Mobile Developer Tools for Lightning Web Components
Learn how to configure your local workspace with the tools needed for developing and testing your mobile-ready Lightning web
components.
• Developer Intermediate
Take your apps to the next level with powerful integration and mobile tools.
6
Create Mobile-Ready Components Validate Your Base Component References
• Create a Lightning app page and add the component to your mobile navigation
Enable your components for Lightning App Builder to allow admins to create Lightning pages with your components. Lightning
app pages and record pages are supported for mobile experiences, such as the Salesforce mobile app and custom mobile apps. If
you surface your component in a custom tab instead, make it available to the mobile app via App Manager or Salesforce Navigation
in Setup.
IN THIS SECTION:
Validate Your Base Component References
Base components help you develop apps quickly. However, not all base components are designed for mobile environments. The
SLDS Validator for VS Code can help you determine the mobile readiness of the base components you use.
Use Mobile Validation with Salesforce Lightning Design System
The Salesforce Lightning Design System (SLDS) validator checks your code for SLDS mobile guidelines adherence as you type. If it
finds a potential issue, the validator provides a warning with suggested improvements. These warnings apply to HTML and CSS
code.
• The component doesn’t require interactions that are awkward when performed using touch-based input. For example, side-to-side
scrolling is awkward or not supported on a narrow phone screen.
• The component doesn’t require constant connections to a server-side controller as you interact with it. For example, auto-suggest
look-ups can require a new server request with every search term change you type.
• There are no known issues when the component is used in a non-desktop browser.
The SLDS validator uses the same list of mobile-ready components used by the Component Reference. You can find documentation,
examples, and specifications for all base components in the Component Reference of the Lightning Component Library. Select a
component, then click Example, Documentation, or Specifications.
7
Create Mobile-Ready Components Validate Your Base Component References
Resolve Warnings
To avoid or address validation warnings, consider these options.
• Use only mobile-ready base components. To find these components:
– Open the Component Reference.
– Expand Filters.
– Under Targets, choose Salesforce Mobile App. The filtered list shows only mobile-ready components.
8
Create Mobile-Ready Components Use Mobile Validation with Salesforce Lightning Design
System
• If you’re creating your first mobile-ready component, start with Create Mobile-Ready Components.
9
Create Mobile-Ready Components Use Mobile Validation with Salesforce Lightning Design
System
px 14 px or larger
pt 10.5 pt or larger
% 87.5 or larger
For specific use case recommendations, see Follow Accessible Mobile Design Guidelines on page 16.
Word wrapping in labels
To avoid truncation at runtime, always use word wrapping in labels. Avoid using the ellipsis.
Clickable images, Button icons, form elements
To clarify UI behavior, always provide labels for visual elements that support user interaction.
2. From the Quick Fix submenu, choose to suppress either the warning for the current line only, or all SLDS warnings for the current
file.
10
Create Mobile-Ready Components Minimize Bandwidth Usage
To remind itself—and you—of suppressed mobile readiness warnings, the SLDS validator inserts code comments. If you’d like to pre-empt
these warnings manually in HTML files, you can insert the comments yourself as follows:
• Any content that is between the following pair of lines is exempt from SLDS validation:
<!-- sldsValidatorIgnore -->
...
<!-- sldsValidatorAllow -->
• The following line exempts the immediate next line from SLDS validation:
<!-- sldsValidatorIgnoreNextLine -->
• If the line <!-- sldsValidatorAllow --> doesn’t exist elsewhere in the HTML file, the following line at the top of the
file exempts the file’s entire content from SLDS validation:
<!-- sldsValidatorIgnore -->
SEE ALSO:
SLDS: Accessible Mobile Design Guidelines
SLDS: Design Tokens
W3C CSS Tips and Tricks
11
Create Mobile-Ready Components Create Responsive Layouts
Prioritize vector graphics, also known as SVG images, as they are often smaller in file size, and scale efficiently at any screen sizes. To use
a raster image, such as a JPEG or PNG file, follow general responsive design guidelines and consider provisioning raster images only for
high-resolution screens. Check the screen resolution for the devices you plan to support. Prepare an image for various resolutions and
serve the best quality image corresponding to the screen size. See Use SVG Resources.
SEE ALSO:
MDN: Responsive Images
Note: To vary functionality across devices, or to create a mobile version of a large existing site, consider creating a separate mobile
site or app. In these cases, creating something new may be easier that creating a responsive layout.
The first step in creating a responsive layout is to implement a fluid grid. The SLDS grid utility provides a mobile-first layout system with
granular column control. To implement the grid system in a Lightning web component, use the lightning-layout and
lightning-layout-item base components. When implementing fluid grids, the layout starts to break down at specific breakpoints.
To resolve this layout issue, media queries determine how the layout should look at each breakpoint. These responsive breakpoints are
built into lightning-layout-item, enabling you to define how each column adjusts to the screen size.
Let’s start with a one-column grid. Despite being simple visually, in this example there are three separate levels of containment. The
lightning-card base component defines a container with rounded corners around the content. The lightning-layout
base component creates a wrapper around the content using the slds-grid class. The lightning-layout-item component
creates columns using the slds-col class.
<!-- Page header here -->
<!-- Start page content -->
<lightning-card>
<lightning-layout>
<lightning-layout-item padding="around-small">
<p>Main Content Goes Here</p>
</lightning-layout-item>
</lightning-layout>
12
Create Mobile-Ready Components Create Responsive Layouts
</lightning-card>
<!-- End page content -->
To increase the number of columns, add another lightning-layout-item with some content.
<lightning-card>
<lightning-layout>
<lightning-layout-item padding="around-small">
<p>Main Content Goes Here</p>
</lightning-layout-item>
<lightning-layout-item padding="around-small">
<p>Sidebar Content Goes Here</p>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
13
Create Mobile-Ready Components Create Responsive Layouts
Let’s make some adjustments so that the content is more readable on mobile. To make each column full width, add size="12". The
12-column grid is the most frequently used SLDS grid. On this grid, the size attribute for lightning-layout-item accepts a
value from 1 to 12.
The multiple-rows attribute on lightning-layout adds a slds-wrap class to the container, which wraps your column to a
new row.
<lightning-card>
<lightning-layout multiple-rows>
<lightning-layout-item size="12" padding="around-small">
<p>Main Content Goes here</p>
</lightning-layout-item>
<lightning-layout-item size="12" padding="around-small">
<p>Sidebar Content Goes Here</p>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
14
Create Mobile-Ready Components Create Responsive Layouts
When we view the page on a tablet or desktop, the sidebar column should align horizontally with the main content column. Specify
the width of the main content such that it takes up 75% of the container width using small-device-size="9". See
lightning-layout-item.
Using just markup, you can provide size details for both desktop/tablet and phone/small mobile. It’s ratio-based and enables the device
to effectively pick the right layout based on its own screen size.
<lightning-card>
<lightning-layout multiple-rows>
<lightning-layout-item size="12"
small-device-size="9"
padding="around-small">
<p>Main Content Goes Here</p>
</lightning-layout-item>
<lightning-layout-item size="12"
small-device-size="3"
padding="around-small">
<p>Sidebar Content Goes Here</p>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
15
Create Mobile-Ready Components Follow Accessible Mobile Design Guidelines
16
Create Mobile-Ready Components Follow Accessible Mobile Design Guidelines
Mobile characteristics like smaller viewport size and reduced processing power can constrain your design for layout, control mechanisms,
and navigation. These constraints impact accessibility for mobile users. For example, imagine touch targets that are too small and cause
a user to abandon your app.
The good news is that mobile devices run on similar web technologies to desktop and can usually handle fully featured websites. To
make your components accessible on mobile, follow general web design and accessibility best practices. Consider the accessibility
guidelines for mobile screens early in your design so there aren’t surprises when you deploy.
Note: Not all base components are mobile-ready. For example, lightning-tabset and lightning-tab are based
on the Tabs SLDS component blueprint. However, the tabs don’t stack on mobile to adapt to a more narrow screen. Refer to the
component reference for device support details.
Padding provides spacing around your content. Use a consistent spacing system to keep your app pages neat. We recommend using
the SLDS padding utility for a consistent layout throughout your app. Besides padding, use the various SLDS utilities for alignment,
margin, text, and many others.
Colors on a mobile screen are especially important because users have to deal with glare and movement. Text and informational icons
should have good color contrast. Aim for a color contrast ratio of 4.5:1 or higher for regular-sized text, 3:1 for icons and large text. Large
text is 24 px or more, or 18 px for bold text.
17
Create Mobile-Ready Components Follow Accessible Mobile Design Guidelines
using a gesture, provide a button or other control to trigger an action. You can enable gestures as shortcuts for users who perform a
task repeatedly. If you use a custom gesture, include assistive text to describe the behavior.
Note: For security reasons, these methods aren’t supported: window.open, window.location, and location.href.
To navigate to an external URL, use lightning/navigation with the standard__webPage attribute.
1. Tap target size: The tap target consists of the visual signifier, the container (if there is one), and the internal or external padding. The
minimum size is 44px.
18
Create Mobile-Ready Components Disable Pull-to-Refresh in the Salesforce Mobile App
2. Internal padding: Changes based on the size of the visual signifier used.
3. Visual signifier: An avatar, icon, image, or text. The size can change but the tap target cannot go below 44px.
See the WCAG guidelines.
SEE ALSO:
Lightning Design System: Accessible Mobile Design Guidelines
MDN: Mobile Accessibility
Lightning Web Components Developer Guide: Component Accessibility
19
Create Mobile-Ready Components Disable Pull-to-Refresh in the Salesforce Mobile App
This event has no effect outside the Salesforce mobile app. You can include it on pages that are shared between desktop and mobile
without affecting the behavior of Salesforce for your desktop users.
Component Template
This component has no user interface. Its only purpose is to fire the event that disables pull-to-refresh. As such, the component
template is empty.
<!-- disablePullToRefresh.html -->
<template>
<!-- This component has no user interface -->
<!-- It just fires its event, and is done -->
</template>
Component Implementation
The component does one thing: fire the event that disables pull-to-refresh as soon as it’s loaded. It defines a function that fires the
event, and calls that function in the connectedCallback lifecycle hook.
// disablePullToRefresh.js
import { LightningElement } from 'lwc';
20
Create Mobile-Ready Components Disable Pull-to-Refresh in the Salesforce Mobile App
SEE ALSO:
Lightning Web Components Developer Guide: XML Configuration File Elements
Lightning Web Components Developer Guide: Lifecycle Hooks
Lightning Web Components Developer Guide: Create and Dispatch Events
21
CHAPTER 3 Use Mobile Device Features in Mobile Apps
In this chapter ... Mobile capabilities let you use mobile device features from within a Lightning web component. Access
camera and location detection hardware, and platform features like contacts and calendar data, right
• Request an App from your component code. Build Lightning apps that feel like native mobile apps using these
Review on a Mobile mobile-specific features.
Device
Mobile capabilities are built by Salesforce using the Nimbus framework. Nimbus creates a bridge between
• Scan Barcodes on a
Lightning web components and a mobile device’s native operating system and hardware. Nimbus plugins
Mobile Device
use the Nimbus framework, and are compiled into Salesforce mobile apps, with each plugin providing
• Access a Mobile access to a specific feature area.
Device’s Biometrics
Capabilities Nimbus plugins expose native features to Lightning web components through JavaScript APIs, allowing
you to easily access these features in your Lightning web components.
• Manage Calendar
Events on a Mobile Mobile capabilities built with Nimbus can only be used when your Lightning web component runs in a
Device supported mobile app running on a mobile device. They are built on, and depend on, compiled code
• Access Contacts on included in the mobile app. They cannot be used on desktop, or in a mobile web browser.
a Mobile Device
• Scan Documents on
a Mobile Device
Mobile Capabilities Compatibility Summary
• Use Location on a
Mobile capabilities are supported individually by each Salesforce mobile app. Not every mobile capability
Mobile Device
is supported in every mobile app. The following table provides a compatibility overview, but see the
• Interact with NFC
compatibility topic for each mobile capability for full compatibility details.
Tags on a Mobile
Device
Mobile Salesforce Salesforce Mobile Field Service
Capability Mobile Mobile App Publisher Mobile
Plus
AppReviewService
BarcodeScanner
See note.
BiometricsService
CalendarService
iOS only.
ContactsService
iOS only.
DocumentScanner
LocationService
Android only.
22
Use Mobile Device Features in Mobile Apps
Note: The Field Service Mobile app provides an alternative implementation of BarcodeScanner.
See Scan Barcodes on a Mobile Device in the Field Service Developer Guide for details.
23
Use Mobile Device Features in Mobile Apps Request an App Review on a Mobile Device
Important: AppReviewService does not and cannot function when running in a web browser, whether on a desktop or mobile
device.
IN THIS SECTION:
AppReviewService User Experience
Your component can deliver any user experience you desire.
Use the AppReviewService API
To develop a Lightning web component with app review features, use the AppReviewService API.
AppReviewService Example
Here’s a minimal but complete example of a Lightning web component that uses AppReviewService to request an app review.
Compatibility and Requirements
AppReviewService is a JavaScript module that provides an API to Lightning web components to make mobile hardware and platform
(operating system) features available in JavaScript. It requires access to device hardware and device platform APIs. This access is
only available when AppReviewService runs within a compatible Salesforce mobile app. It does not and cannot function when
running in a standard web browser, whether the browser runs on a desktop or mobile device.
Considerations and Limitations
Consider these guidelines and limitations when developing features that use the AppReviewService API.
SEE ALSO:
Lightning Web Components Developer Guide: AppReviewService API
24
Use Mobile Device Features in Mobile Apps AppReviewService User Experience
25
Use Mobile Device Features in Mobile Apps AppReviewService User Experience
3. After users rate the app, they can submit their rating to the app stores.
26
Use Mobile Device Features in Mobile Apps Use the AppReviewService API
After it’s imported into your component, use the factory function to get an instance of AppReviewService. With your AppReviewService
instance, use the utility functions and constants to verify availability. Use the app review related functions to perform app review
operations.
27
Use Mobile Device Features in Mobile Apps AppReviewService Example
SEE ALSO:
Lightning Web Components Developer Guide: AppReviewService API
AppReviewService Example
AppReviewService Example
Here’s a minimal but complete example of a Lightning web component that uses AppReviewService to request an app review.
The component’s HTML template contains a button to request an app review.
<!-- appReviewFeedbackServiceExample.html -->
<template>
<lightning-card title="App Review Feedback" icon-name="custom:custom14">
<div class="slds-var-m-around_medium">
<div>Hello, {name}!</div>
28
Use Mobile Device Features in Mobile Apps AppReviewService Example
<div class="slds-var-m-top_x-small">
<lightning-button label="Request App Review" value="Action"
onclick={handleBeginClick}></lightning-button>
</div>
</div>
</lightning-card>
</template>
get name() {
return userName || "Guest User";
}
handleBeginClick(event) {
const myAppReviewService = getAppReviewService();
if (myAppReviewService.isAvailable()) {
myAppReviewService.requestAppReview(null)
.then(() => {
// Do something with success response
console.log("App review request complete successfully");
})
.catch((error) => {
// Handle cancellation and scanning errors here
console.error(error);
});
}
else {
// Handle with message, error, beep, and so on
console.error("App Review service not available");
}
}
}
SEE ALSO:
Use the AppReviewService API
29
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
30
Use Mobile Device Features in Mobile Apps Scan Barcodes on a Mobile Device
AppReviewService doesn’t implement an app review feature itself. Instead, it makes available the native features of the underlying
platform (Android or iOS). While the features provided by AppReviewService are the same across both, it’s subject to platform-specific
quirks and minor differences.
AppReviewService Considerations
Be aware of the following considerations when using AppReviewService in your Lightning app.
• AppReviewService is built on top of mobile operating system and device features. AppReviewService’s capabilities therefore depend
on Android or iOS features, which are subject to change beyond our control. When mobile operating system features change, the
behavior of AppReviewService can change without notice.
• A Lightning component that uses AppReviewService can have a custom user interface in the component itself.
Important: BarcodeScanner does not and cannot function when running in a web browser, whether running on a desktop or
mobile device.
BarcodeScanner provides to your component a string value of the data encoded in a scanned barcode. It doesn't attempt to interpret
or process the decoded value.
IN THIS SECTION:
Barcode Scanning User Experience
Your component can deliver any user experience you desire, but there’s a common flow for any component that can scan a barcode.
Use the BarcodeScanner API
To develop a Lightning component with barcode scanning features, use the BarcodeScanner API.
BarcodeScanner Example–Modern Scanning API
Here’s a complete example of a Lightning web component that uses BarcodeScanner to scan multiple barcodes simultaneously and
process them in a batch after scanning is completed.
BarcodeScanner Example—Single Scan (Legacy)
Here’s a minimal but complete example of a Lightning web component that uses BarcodeScanner to recognize a barcode.
Scan Multiple Barcodes (Legacy)
To scan multiple barcodes in a single scanning session, use resumeCapture() to create a continuous scanning cycle that scans
barcodes until the user clicks the Cancel button.
BarcodeScanner Example—Continuous Scanning (Legacy)
Here’s a minimal but complete example of a Lightning web component that uses BarcodeScanner to scan for and recognize multiple
barcodes in a continuous cycle.
Create a Self-Service Kiosk Application
Use BarcodeScanner with a device’s front-facing camera to create applications suitable for use as an unattended self-service kiosk.
BarcodeScanner Example—Self-Service Kiosk (Legacy)
Here’s a complete example of a Lightning web component with BarcodeScanner that could serve as a self-service kiosk.
31
Use Mobile Device Features in Mobile Apps Barcode Scanning User Experience
SEE ALSO:
Lightning Web Components Developer Guide: BarcodeScanner API
2. When the button is pressed, BarcodeScanner invokes the mobile device’s user interface for the camera and barcode scanning
function. When the camera detects a valid barcode, it displays a bounding box around the barcode, reads the data from the barcode,
and returns the result to the Lightning web component that invoked it.
32
Use Mobile Device Features in Mobile Apps Barcode Scanning User Experience
3. The Lightning web component displays or otherwise processes the results of the scan.
33
Use Mobile Device Features in Mobile Apps Use the BarcodeScanner API
Important: We recommend using the modern scan() and dismiss() API functions in your LWC scanning code to
streamline your development experience. The legacy API functions beginCapture(), resumeCapture(), and
endCapture() are still available, but will be retired in a future release. See Understand BarcodeScanner Modern and Legacy
APIs on page 35 for additional details.
After it’s imported into your component, use the factory function to get an instance of BarcodeScanner. With your BarcodeScanner
instance, use the utility functions and constants to verify scanner availability and to configure scans. Use the scanning lifecycle functions
to perform scanning operations.
Scan a Barcode
Scanning with BarcodeScanner is simple using the scanning lifecycle functions.
1. Start a scan with scan(options).
2. Handle the result of the scan, which is returned in the form of a promise.
3. End the scan with dismiss().
34
Use Mobile Device Features in Mobile Apps Use the BarcodeScanner API
For example:
myScanner.scan(scanningOptions)
.then((result) => {
// Do something with the result of the scan
console.log(result);
this.scannedBarcode = result.value;
})
.catch((error) => {
// Handle cancellation and scanning errors here
console.error(error);
})
.finally(() => {
myScanner.dismiss();
});
See scan(options) for more details of how to handle scan results, handle errors, and so on.
IN THIS SECTION:
Understand BarcodeScanner Modern and Legacy APIs
In previous versions of BarcodeScanner, scanning a single barcode in a scanning session required a different programmatic approach
than scanning several barcodes in a row without requiring user intervention after each scan. Now, BarcodeScanner has new APIs to
streamline the development experience for these common use cases, and new capabilities to scan large quantities of barcodes more
efficiently.
Understand the BarcodeScanner Scanning Lifecycle
BarcodeScanner has four distinct scanning modes, each appropriate for different use cases.
SEE ALSO:
Lightning Web Components Developer Guide: BarcodeScanner API
BarcodeScanner Example–Modern Scanning API
BarcodeScanner Example—Single Scan (Legacy)
35
Use Mobile Device Features in Mobile Apps Use the BarcodeScanner API
Note: If you’re adding BarcodeScanner to your LWC for the first time, use the modern APIs. There’s no advantage to using the
legacy APIs, and you’ll eventually have to switch to the modern APIs anyway, when the retirement of the legacy APIs becomes
official.
If you have an existing LWC that uses the legacy APIs, we encourage you to update your code to use the modern APIs as soon as
possible, so you can enjoy a more streamlined development experience and also have access to the new bulk scanning and
multi-scanning capabilities.
The following table summarizes the relationships of the legacy APIs to the modern APIs replacing them:
endCapture() dismiss()
SEE ALSO:
Lightning Web Components Developer Guide: BarcodeScanner API
Understand the BarcodeScanner Scanning Lifecycle
Use the BarcodeScanner API
Single Scanning
Single scanning mode consists of scanning a single barcode, followed immediately by processing the barcode data.
Single scanning is ideal when the use case is a situation where user interaction is desired right after the barcode is scanned. For example,
if your application seeks to confirm the user’s identity, one possible implementation starts with a barcode scan and then immediately
prompts the user to answer a security question before the next user can scan their barcode.
36
Use Mobile Device Features in Mobile Apps BarcodeScanner Example–Modern Scanning API
Continuous Scanning
Continuous scanning mode consists of scanning several barcodes, one after the other, processing each one after it’s scanned.
Continuous scanning is ideal where only one barcode must be scanned at a time and the processing must take place after each scan.
For example, if your application relates to inventory management in a warehouse, one possible implementation involves employees
scanning many items, one at a time, updating the inventory system in real-time and prompting inventory managers to reorder more of
a given product if stock runs low.
37
Use Mobile Device Features in Mobile Apps BarcodeScanner Example–Modern Scanning API
The HTML template provides a minimal scanning user interface. There’s an element to display the results of the scans in a list view, a bit
of static help text, and a button to start scanning.
<!-- After barcodes are scanned, their values are displayed here: -->
<template lwc:if={scannedBarcodes}>
<div class="slds-var-m-vertical_large slds-var-p-vertical_medium slds-border_top
slds-border_bottom">
<p>Scanned barcode values are:</p>
<pre>{scannedBarcodesAsString}</pre>
</div>
</template>
</template>
This example displays all the values of successful scans in a list view. It’s a streamlined example, emphasizing the scanning lifecycle of
the modern scanning APIs.
// barcodeScannerMultiScan.js
import { LightningElement, track } from "lwc";
import { getBarcodeScanner } from "lightning/mobileCapabilities";
connectedCallback() {
this.barcodeScanner = getBarcodeScanner();
}
38
Use Mobile Device Features in Mobile Apps BarcodeScanner Example–Modern Scanning API
beginScanning() {
// Set your configuration options, including bulk and multi-scanning if desired, in
this scanningOptions object
const scanningOptions = {
barcodeTypes: [this.barcodeScanner.barcodeTypes.QR],
scannerSize: "FULLSCREEN",
cameraFacing: "BACK",
showSuccessCheckMark: true,
enableBulkScan: true,
enableMultiScan: true,
};
processScannedBarcodes(barcodes) {
// Do something with the barcode scan value:
// - look up a record
// - create or update a record
// - parse data and put values into a form
// - and so on; this is YOUR code
console.log(JSON.stringify(barcodes));
this.scannedBarcodes = this.scannedBarcodes.concat(barcodes);
}
processError(error) {
// Check to see if user ended scanning
if (error.code == "USER_DISMISSED") {
console.log("User terminated scanning session.");
} else {
console.error(error);
}
}
39
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Single Scan (Legacy)
get scannedBarcodesAsString() {
return this.scannedBarcodes.map((barcode) => barcode.value).join("\n");
}
}
SEE ALSO:
Use the BarcodeScanner API
Important: We recommend using the modern scan() and dismiss() API functions in your LWC scanning code to
streamline your development experience. The legacy API functions beginCapture(), resumeCapture(), and
endCapture() are still available, but will be retired in a future release. See Understand BarcodeScanner Modern and Legacy
APIs on page 35 for additional details.
The HTML template provides the bare minimum for a scanning user interface. There’s an element to display the results of a scan, a bit
of static help text, and a button to start a scan. The only thing mildly interesting is the use of the disabled attribute to disable the
scan button when not on a mobile device. This attribute is set based on the results of isAvailable() when the component is
initialized.
<!-- barcodeScannerExample.html -->
<template>
<div class="slds-text-align_center">
<span class="slds-text-heading_large">BarcodeScanner: Single Scan</span>
</div>
40
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Single Scan (Legacy)
icon-name="utility:scan"
label="Scan Barcode"
title="Open a camera view and look for a barcode to scan"
onclick={handleBeginScanClick}>
</lightning-button>
</div>
</template>
This simple example displays the decoded value of a successful scan. It also displays a toast-style message based on the results of the
scan. Each phase of the scanning lifecycle writes a console message.
// barcodeScannerExample.js
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { getBarcodeScanner } from 'lightning/mobileCapabilities';
handleBeginScanClick(event) {
// Reset scannedBarcode to empty string before starting new scan
this.scannedBarcode = '';
41
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Single Scan (Legacy)
if (error.code == 'userDismissedScanner') {
// User clicked Cancel
this.dispatchEvent(
new ShowToastEvent({
title: 'Scanning Cancelled',
message:
'You cancelled the scanning session.',
mode: 'sticky'
})
);
}
else {
// Inform the user we ran into something unexpected
this.dispatchEvent(
new ShowToastEvent({
title: 'Barcode Scanner Error',
message:
'There was a problem scanning the barcode: ' +
error.message,
variant: 'error',
mode: 'sticky'
})
);
}
})
.finally(() => {
console.log('#finally');
// Let user know they need to use a mobile phone with a camera
this.dispatchEvent(
new ShowToastEvent({
42
Use Mobile Device Features in Mobile Apps Scan Multiple Barcodes (Legacy)
SEE ALSO:
BarcodeScanner Example–Modern Scanning API
Use the BarcodeScanner API
Important: We recommend using the modern scan() and dismiss() API functions in your LWC scanning code to
streamline your development experience. The legacy API functions beginCapture(), resumeCapture(), and
endCapture() are still available, but will be retired in a future release. See Understand BarcodeScanner Modern and Legacy
APIs on page 35 for additional details.
Sometimes you want to scan many barcodes in a row, without requiring user interaction between scans. For example, when scanning
a shelf of inventory, you might not want to stop after each item, or to click a Scan button for every item. In these cases, it can make more
sense to click Scan once, and then scan barcodes repeatedly until done with all of the items. Implementing a continuous scanning cycle
like this is slightly different from scanning a single item.
1. Start a scanning session as usual, with beginCapture().
2. When the promise resolves, process the scanned barcode as usual, in the then() block.
Note: Processing the barcode can’t change the user interface, or require interacting with the user. That needs to wait until
after the scanning cycle completes.
3. At the end of the then() block, call a new continue scanning function, which uses resumeCapture() to continue the current
scanning session.
4. Call endCapture() at the end of the catch() block, instead of in the finally() block.
5. When the user clicks Cancel to end the scanning session, BarcodeScanner returns a BarcodeScannerError object
with a code property value of userDismissedScanner. Handle cancellation and actual errors in the catch() block.
43
Use Mobile Device Features in Mobile Apps Scan Multiple Barcodes (Legacy)
singleScanner.beginCapture(scanningOptions) sessionScanner.beginCapture(scanningOptions)
this.processScannedBarcode(scannedBarcode) this.processScannedBarcode(scannedBarcode)
this.continueScanning();
) )
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
sessionScanner.endCapture();
}) });
.finally(() => {
singleScanner.endCapture();
});
continueScanning() {
this.sessionScanner.resumeCapture()
.then((scannedBarcode) => {
this.processScannedBarcode(scannedBarcode);
this.continueScanning();
})
.catch((error) => {
this.processError(error);
this.sessionScanner.endCapture();
});
}
This code should look familiar; it’s nearly identical to the earlier beginCapture() example for continuous scanning. There‘s only
one difference: continueScanning() creates a promise chain by calling sessionScanner.resumeCapture(), while
the earlier example called sessionScanner.beginCapture(). It might be obvious, but you only call beginCapture()
once, at the beginning of a scanning cycle.
While the difference in the code is minor, the difference in the flow of execution is significant. The scanning cycle begins in a promise
chain created by beginCapture(), which executes only once. That initial promise resolves one of two ways:
• If the scan is successful, the barcode result is processed, and then the flow of control for the scanning cycle is handed off to
continueScanning().
44
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Continuous Scanning (Legacy)
• If the user clicks Cancel, or if there’s an error, the promise chain ends in the catch() error handling block, covered in the End
Capture for Continuous Scanning section.
The promise chain in continueScanning() ends the same two ways, with one important difference. While the code is the same,
after a successful scan it continues the scanning cycle by calling itself, creating a recursive loop that continues the scanning cycle until
the user clicks Cancel, or there’s an error.
Whoops. Didn’t mean to scare you with that word, recursive. Yes, continueScanning() ends by calling itself, which makes it a
recursive function. But this recursion is pretty simple—it’s just a loop, an event loop of sorts. The loop handles scan-something events
(in the then() block) until a user-clicked-Cancel event comes along (in the catch() block), and then it ends. It might take a minute,
but you can wrap your head around it.
The overall pattern here is the following:
• You begin a scanning cycle using beginCapture().
• The promise resolution chain from beginCapture() ends in a call to continueScanning(), your own function.
• continueScanning() continues the existing scanning cycle by calling resumeCapture(), but is otherwise the same as
the beginCapture() that started the cycle.
• The promise resolution chain in continueScanning() ends in a call to continueScanning(), creating a scanning cycle
loop.
• The loop ends when the user clicks Cancel, BarcodeScanner rejects the promise with a BarcodeScannerError, and
you call endCapture() in the error handling catch() block.
The code duplication between the beginCapture() and resumeCapture() promise chains is unfortunate, but unavoidable.
Move as much processing code, such as the handling of a scanned barcode, into functions you can call from both chains. In the example
here, processScannedBarcode() is a function that both promise chains use to handle a successful scan. See BarcodeScanner
Example—Continuous Scanning (Legacy) on page 45 for the complete sample, which includes that function’s implementation.
SEE ALSO:
BarcodeScanner Example—Continuous Scanning (Legacy)
45
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Continuous Scanning (Legacy)
Important: We recommend using the modern scan() and dismiss() API functions in your LWC scanning code to
streamline your development experience. The legacy API functions beginCapture(), resumeCapture(), and
endCapture() are still available, but will be retired in a future release. See Understand BarcodeScanner Modern and Legacy
APIs on page 35 for additional details.
The HTML template provides the bare minimum for a scanning user interface. There’s an element to display the results of the scans, a
bit of static help text, and a button to start scanning.
<!-- barcodeScannerContinuous.html -->
<template>
<div class="slds-text-align_center">
<span class="slds-text-heading_large">BarcodeScanner: Multi-Scan</span>
</div>
<!-- After barcode are scanned, their values are displayed here: -->
<template lwc:if={scannedBarcodes}>
<div class="slds-var-m-vertical_large slds-var-p-vertical_medium
slds-text-align_center slds-border_top slds-border_bottom">
Scanned barcode values are:
<span class="slds-text-heading_small">{scannedBarcodesAsString}</span>
</div>
</template>
This example displays all of the values of successful scans, one after the other. This example is streamlined, omitting some of the comments
and processing illustrated in BarcodeScanner Example—Single Scan (Legacy) on page 40, to focus on the scanning cycle itself.
// barcodeScannerContinuous.js
import { LightningElement, track } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { getBarcodeScanner } from 'lightning/mobileCapabilities';
46
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Continuous Scanning (Legacy)
sessionScanner;
@track scannedBarcodes;
connectedCallback() {
this.sessionScanner = getBarcodeScanner();
}
beginScanning() {
// Reset scannedBarcodes before starting new scanning session
this.scannedBarcodes = [];
async continueScanning() {
// Pretend to do some work; see timing note below.
await new Promise((resolve) => setTimeout(resolve, 1000));
this.sessionScanner.resumeCapture()
.then((scannedBarcode) => {
this.processScannedBarcode(scannedBarcode);
this.continueScanning();
})
.catch((error) => {
this.processError(error);
this.sessionScanner.endCapture();
})
}
processScannedBarcode(barcode) {
// Do something with the barcode scan value:
// - look up a record
// - create or update a record
// - parse data and put values into a form
// - and so on; this is YOUR code
47
Use Mobile Device Features in Mobile Apps Create a Self-Service Kiosk Application
console.log(JSON.stringify(barcode));
this.scannedBarcodes.push(barcode);
}
processError(error) {
// Check to see if user ended scanning
if (error.code == 'userDismissedScanner') {
console.log('User terminated scanning session via Cancel.');
}
else {
console.error(error);
}
}
get scannedBarcodesAsString() {
return this.scannedBarcodes.map(barcodeResult => {
return barcodeResult.value;
}).join('\n\n');
}
}
Note: This example doesn’t process a scanned barcode in any meaningful way. As a result, the processScannedBarcode()
function executes quickly—too quickly. It can trigger a timing issue that causes the example to fail. To avoid the issue, we’ve
inserted a one-second delay before starting the next scan. Real-world barcode processing typically takes long enough to avoid
the issue. In that case, you can remove the line with the delay and the async keyword preceding the continueScanning()
function.
See Scan Multiple Barcodes (Legacy) on page 43 for an explanation of how beginScanning() and continueScanning()
work together to create the continuous scanning cycle.
SEE ALSO:
Scan Multiple Barcodes (Legacy)
48
Use Mobile Device Features in Mobile Apps Create a Self-Service Kiosk Application
Whether you want to update an existing LWC component to use the self-service features of BarcodeScanner, or you’re creating a
brand-new component, you only need to keep a few things in mind to get started.
Important: We recommend using the modern scan() and dismiss() API functions in your LWC scanning code to
streamline your development experience. The legacy API functions beginCapture(), resumeCapture(), and
endCapture() are still available, but will be retired in a future release. See Understand BarcodeScanner Modern and Legacy
APIs on page 35 for additional details.
Continuous Scanning Lifecycle
To create a scanner that continuously scans and processes barcode data without manual user intervention, use the resumeCapture()
function in your programming logic to create a continuous scanning lifecycle.
For more information about resumeCapture() and how the scanning lifecycle works under the hood, see Scan Multiple Barcodes
on page 43.
Front-Facing Camera
BarcodeScanner functionality to use the front-facing camera allows for a better user experience when creating a kiosk application. It
allows the screen of your kiosk setup to function as a sort of mirror, which helps your users more easily position their scannable code
(whether the code is on a badge, card, or something else) within the scanner view. To use the front-facing camera in your component,
set the value of the cameraFacing property on the BarcodeScannerOptions object to FRONT.
For more information on this property and other details of configuring BarcodeScanner, see BarcodeScanner Data Types.
Custom Scanner UI
Finally, you’ll want to add your own custom UI to BarcodeScanner to replace the standard, minimal UI. To do this, first build your user
interface as custom, static HTML page. Then provide the HTML for your custom UI as a string for the value of the
backgroundViewHTML property of the BarcodeScannerOptions object.
Note: Your custom UI completely replaces the standard BarcodeScanner UI, including the Cancel button used for dismissing
the scanner. Be sure to include this essential element in your custom UI, as well as any other user interface details, such as custom
graphics or instructions, you want for your component.
For more information on customizing the UI, see Customize the BarcodeScanner User Interface on page 54.
49
Use Mobile Device Features in Mobile Apps Create a Self-Service Kiosk Application
Custom UI
50
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Self-Service Kiosk (Legacy)
SEE ALSO:
BarcodeScanner Example—Self-Service Kiosk (Legacy)
Customize the BarcodeScanner User Interface
Important: We recommend using the modern scan() and dismiss() API functions in your LWC scanning code to
streamline your development experience. The legacy API functions beginCapture(), resumeCapture(), and
endCapture() are still available, but will be retired in a future release. See Understand BarcodeScanner Modern and Legacy
APIs on page 35 for additional details.
The HTML template provides the bare minimum for a scanning user interface. There’s an element to display the results of the scans, a
bit of static help text, and a button to start scanning.
<!-- barcodeScannerKiosk.html -->
<template>
<div class="slds-text-align_center">
<span class="slds-text-heading_large">BarcodeScanner: Multi-Scan</span>
</div>
<!-- After barcode are scanned, their values are displayed here: -->
<template lwc:if={scannedBarcodes}>
<div class="slds-var-m-vertical_large slds-var-p-vertical_medium
slds-text-align_center slds-border_top slds-border_bottom">
Scanned barcode values are:
<span class="slds-text-heading_small">{scannedBarcodesAsString}</span>
</div>
</template>
51
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Self-Service Kiosk (Legacy)
</div>
<!-- Custom UI for the scanner is defined here. We set display:none here because the
scanner will show this. -->
<div data-id="BarcodeScannerCustomUI" style="display: none;">
<div>
<h1 align="right"><a style="text-decoration: none;"
href="nimbusbarcodescanner://dismiss"> </a></h1>
<h2 align="center">Welcome, let's get you verified!</h2>
<h3 align="center">Point the front side of your Health Card<br>at the camera on
this device.</h3>
</div>
</div>
</template>
This example borrows heavily from the code sample in BarcodeScanner Example—Continuous Scanning (Legacy) on page 45. The
differences in this example provide all the basic elements needed for a self-service kiosk use case. It uses the front-facing camera for
scanning, employs a continuous scanning lifecycle to minimize the need for user interaction, and even defines and uses a custom UI.
// barcodeScannerKiosk.js
import { LightningElement, track } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { getBarcodeScanner } from 'lightning/mobileCapabilities';
sessionScanner;
@track scannedBarcodes;
connectedCallback() {
this.sessionScanner = getBarcodeScanner();
}
beginScanning() {
// Reset scannedBarcodes before starting new scanning session
this.scannedBarcodes = [];
// Specify the size of the scanner camera view, use of the front-facing camera,
and pull in the custom UI defined above
const scanningOptions = {
"barcodeTypes": [this.sessionScanner.barcodeTypes.QR],
"scannerSize": "XLARGE",
"cameraFacing": "FRONT",
"showSuccessCheckMark": true,
"presentWithAnimation": false,
"backgroundViewHTML": backgroundViewHTML
52
Use Mobile Device Features in Mobile Apps BarcodeScanner Example—Self-Service Kiosk (Legacy)
};
this.sessionScanner.beginCapture(scanningOptions)
.then((scannedBarcode) => {
this.processScannedBarcode(scannedBarcode);
this.continueScanning();
})
.catch((error) => {
this.processError(error);
this.sessionScanner.endCapture();
})
}
else {
console.log("BarcodeScanner unavailable. Non-mobile device?");
}
}
async continueScanning() {
// Pretend to do some work; see timing note below.
await new Promise((resolve) => setTimeout(resolve, 1000));
this.sessionScanner.resumeCapture()
.then((scannedBarcode) => {
this.processScannedBarcode(scannedBarcode);
this.continueScanning();
})
.catch((error) => {
this.processError(error);
this.sessionScanner.endCapture();
})
}
processScannedBarcode(barcode) {
// Do something with the barcode scan value:
// - look up a record
// - create or update a record
// - parse data and put values into a form
// - and so on; this is YOUR code
console.log(JSON.stringify(barcode));
this.scannedBarcodes.push(barcode);
}
processError(error) {
// Check to see if user ended scanning
if (error.code == 'userDismissedScanner') {
console.log('User terminated scanning session via Cancel.');
}
else {
console.error(error);
}
}
get scannedBarcodesAsString() {
return this.scannedBarcodes.map(barcodeResult => {
53
Use Mobile Device Features in Mobile Apps Customize the BarcodeScanner User Interface
return barcodeResult.value;
}).join('\n\n');
}
}
Note: This example doesn’t process a scanned barcode in any meaningful way. As a result, the processScannedBarcode()
function executes quickly—too quickly. It can trigger a timing issue that causes the example to fail. To avoid the issue, we’ve
inserted a one-second delay before starting the next scan. Real-world barcode processing typically takes long enough to avoid
the issue. In that case, you can remove the line with the delay and the async keyword preceding the continueScanning()
function.
See Scan Multiple Barcodes (Legacy) on page 43 for an explanation of how beginScanning() and continueScanning()
work together to create the continuous scanning cycle.
SEE ALSO:
Create a Self-Service Kiosk Application
Customize the BarcodeScanner User Interface
You can use a static HTML string, or generate the HTML at runtime. There are only a few requirements.
• The <header> element is required, and should not be modified. Confine your customizations to the <html> and child elements
of the page.
• You should also provide a UI element to dismiss or cancel the scanning session. See Dismiss the Scanner.
54
Use Mobile Device Features in Mobile Apps Customize the BarcodeScanner User Interface
To apply your custom UI to BarcodeScanner, set the backgroundViewHTML property of the BarcodeScannerOptions
configuration object to the string value of your HTML page, including the <header>. Then provide BarcodeScannerOptions
when calling beginCapture().
UI Customization Layers
Your custom UI overlays — and completely hides — all parts of the standard BarcodeScanner UI. The following diagram illustrates the
layers of the scanner UI as rendered by BarcodeScanner:
55
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
Place this anywhere in your custom user interface that makes sense.
Considerations
• The camera view is always placed in the center of the device screen (horizontally and vertically), and is superimposed onto your
custom UI. Consider this when designing your custom UI, and avoid having essential parts of the UI obscured by the camera view.
• The custom UI is rendered in a separate webview container than the main webview container that hosts your Lightning web
component. The HTML that renders your custom UI can’t reference or access elements or objects that are defined in your component.
• Note: This plugin is not supported in the Field Service mobile app.
Note: The Field Service Mobile app provides an alternative implementation of BarcodeScanner. See Scan Barcodes on a Mobile
Device in the Field Service Developer Guide for details.
BarcodeScanner is fully functional when used in a Lightning app or Lightning site run from one of these Salesforce apps on a compatible
iOS or Android mobile device. See Requirements for the Salesforce Mobile App, or the requirements page for your target mobile app,
for specific device and operating system requirements.
BarcodeScanner is not fully functional when running on other devices, such as a desktop, or when running in a web browser, even on
a mobile device. It requires one of the mobile apps listed above. The BarcodeScanner API is accessible in Lightning Experience on all
devices, so your code won’t fail due to missing functions. However, when your app runs in a browser—desktop or mobile—it can use
only BarcodeScanner constants and utility functions. Attempting any scanning operation will fail.
Code 39 CODE_39
Code 93 CODE_93
56
Use Mobile Device Features in Mobile Apps Considerations and Limitations
Interleaved 2 of 5 ITF
PDF417 PDF_417
QR-Code QR
• BarcodeScanner doesn’t implement scanning itself. Instead, it makes available the scanning feature of the underlying platform
(Android or iOS). While the features provided by BarcodeScanner are the same across both platforms, it is subject to some
platform-specific quirks and minor differences.
– If you can’t get a clear picture of the barcode, it can’t be recognized. The quality of the device camera affects barcode recognition.
A damaged or low-quality camera lens or focusing system, poor lighting, motion, and other factors can make it difficult or
impossible to get a clear picture of a barcode.
– The quality of the barcode affects barcode recognition. Specifically, damaged or obscured barcodes are hard to recognize
successfully.
• If you’re having trouble getting BarcodeScanner to recognize a barcode, try the following:
– First, verify that the barcode type is one of the supported barcode symbologies. There are other barcode types that aren’t
supported.
– Second, verify that you’ve configured BarcodeScanner to recognize the expected symbology. See BarcodeScannerOptions
in BarcodeScanner Data Types for configuration details.
57
Use Mobile Device Features in Mobile Apps Access a Mobile Device’s Biometrics Capabilities
– Finally, check whether another app on the same device is able to recognize the barcode. If the standard camera app on the
device can’t recognize the barcode, neither can BarcodeScanner.
Development Considerations
• BarcodeScanner requires access to camera hardware. To test scanning during development, use actual, physical devices.
– The Android emulator can simulate camera hardware by using a webcam on your development system. To do so, edit the camera
configuration for your Android Virtual Device, in the advanced settings panel. However, the camera built into most laptops is
much lower quality than what’s found on modern mobile phones. A low-quality camera limits the usefulness of testing barcode
recognition.
– The iOS simulator doesn’t provide access to simulated camera hardware at all.
You can certainly develop the user experience for your component on a desktop or laptop development system. But be sure to test
scanning functionality on the physical devices on which you plan to deploy your Lightning app.
BarcodeScanner Considerations
Be aware of the following considerations when using BarcodeScanner in your Lightning app.
• BarcodeScanner is built on top of mobile operating system features. BarcodeScanner’s scanning capabilities therefore depend on
Android or iOS features, which are subject to change beyond our control. When mobile operating system features change, the
behavior of BarcodeScanner can change without notice.
• BarcodeScanner provides haptic feedback (a short vibration) after a successful scan on iOS devices. There’s no haptic feedback on
Android devices.
Important: BiometricsService does not and cannot function when running in a web browser, whether on a desktop or mobile
device.
IN THIS SECTION:
BiometricsService User Experience
Your component can deliver any user experience you desire, but there’s a common flow for any component that calls for a biometrics
check.
Use the BiometricsService API
To develop a Lightning web component with biometrics-checking features, use the BiometricsService API as your method for
accessing a device’s native biometrics functionality.
BiometricsService Example
Here’s a basic example of a Lightning web component that uses a device’s biometrics capabilities to verify device ownership.
Compatibility and Requirements
BiometricsService is a JavaScript module that provides an API to Lightning web components to make mobile hardware and platform
(operating system) features available in JavaScript. It requires access to device hardware and device platform APIs. This access is
only available when BiometricsService runs within a compatible Salesforce mobile app. It does not and cannot function when
running in a standard web browser, whether the browser runs on a desktop or mobile device.
58
Use Mobile Device Features in Mobile Apps BiometricsService User Experience
SEE ALSO:
Lightning Web Components Developer Guide: BiometricsService API
After it’s imported into your component, use the factory function to get an instance of BiometricsService. With your BiometricsService
instance, use the utility functions and constants to verify availability. Then use the feature functions to perform the associated functionality.
59
Use Mobile Device Features in Mobile Apps Use the BiometricsService API
SEE ALSO:
Lightning Web Components Developer Guide: BiometricsService API
BiometricsService Example
60
Use Mobile Device Features in Mobile Apps BiometricsService Example
BiometricsService Example
Here’s a basic example of a Lightning web component that uses a device’s biometrics capabilities to verify device ownership.
The component’s HTML template is minimal, with a “Verify” button to initiate the biometrics check.
<template>
<lightning-card title="Biometrics Service Demo" icon-name="custom:privately_shared">
<div class="slds-var-m-around_medium">
Use device biometrics capabilities to verify current user is indeed device owner:
<lightning-button
variant="brand"
label="Verify"
title="Verify device ownership using biometrics"
onclick={handleVerifyClick}
class="slds-var-m-left_x-small">
</lightning-button>
</div>
<div class="slds-var-m-around_medium">
<lightning-formatted-text value={status}></lightning-formatted-text>
</div>
</lightning-card>
</template>
This example simply uses BiometricsService to prompt the user to complete a biometrics check. A status message is returned, indicating
whether the check was successful or not.
import { LightningElement } from 'lwc';
import { getBiometricsService } from 'lightning/mobileCapabilities';
connectedCallback() {
this.biometricsService = getBiometricsService();
}
handleVerifyClick() {
if (this.biometricsService.isAvailable()) {
const options = {
permissionRequestBody: "Required to confirm device ownership.",
additionalSupportedPolicies: ['PIN_CODE']
};
this.biometricsService.checkUserIsDeviceOwner(options)
.then((result) => {
// Do something with the result
if (result === true) {
this.status = " Current user is device owner."
} else {
this.status = " Current user is NOT device owner."
}
})
.catch((error) => {
// Handle errors
this.status = 'Error code: ' + error.code + '\nError message: ' + error.message;
61
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
});
} else {
// service not available
this.status = 'Problem initiating Biometrics service. Are you using a mobile
device?';
}
}
}
SEE ALSO:
Use the BiometricsService API
62
Use Mobile Device Features in Mobile Apps Manage Calendar Events on a Mobile Device
Important: CalendarService does not and cannot function when running in a web browser, whether on a desktop or mobile
device.
IN THIS SECTION:
CalendarService User Experience
Your component can deliver any user experience you like. There are a number of common calendar-based features where
CalendarService might be suitable.
Use the CalendarService API
To develop a Lightning web component with calendar-based features, use the CalendarService API as your method for accessing a
device’s native calendar functionality.
CalendarService Example
Here’s a basic example of a Lightning web component that displays calendar events and allows the user to perform basic
calendar-related functions.
Compatibility and Requirements
CalendarService is a JavaScript module that provides an API to Lightning web components to make mobile hardware and platform
(operating system) features available in JavaScript. It requires access to device hardware and device platform APIs. This access is only
available when CalendarService runs within a compatible Salesforce mobile app. It does not and cannot function when running
in a standard web browser, whether the browser runs on a desktop or mobile device.
Considerations and Limitations
Keep the following in mind when developing features that use the CalendarService API.
SEE ALSO:
Lightning Web Components Developer Guide: CalendarService API
63
Use Mobile Device Features in Mobile Apps Use the CalendarService API
In some of these examples, CalendarService is only a part of the complete solution. Displaying event data, checking a calendar for
availability, and so on are other parts that you need to implement yourself.
After it’s imported into your component, use the factory function to get an instance of CalendarService. With your CalendarService
instance, use the utility functions and constants to verify availability. Then use calendar-related functions to perform the associated
functionality.
Get Calendars
It’s simple to import device calendars into your Lightning web component using CalendarService. First, use getCalendars() to
enable access within your component to available device calendars. Then, process the calendar data in whatever manner you wish.
For example:
64
Use Mobile Device Features in Mobile Apps Use the CalendarService API
Get Events
Fetch all calendar events within a specified date range with the getEvents() function. First, call the getEvents() function
with the necessary parameters. Then, process or display event data in whatever manner you wish.
For example, if your calendar component has a “week view” and a “month view,” the startDateSecondsUTC and
endDateSecondsUTC parameters need to be adjusted to capture the appropriate date range to be displayed. If you don’t want to
display events from all mobile device calendars, specify the ones you want to work with in the calendars[] array.
For example:
// Get events from a specified date range on the specified calendar(s), and process them
myCalendarService.getEvents(startDateSecondsUTC, endDateSecondsUTC, calendars, options)
.then((results) => {
// Do something with the event(s) data
this.events = results;
console.log(results);
})
.catch((error) => {
// Handle errors here
this.events = [];
console.error('Error code: ' + error.code); +
console.error('Error message: ' + error.message);
});
65
Use Mobile Device Features in Mobile Apps Use the CalendarService API
Warning: Using updateEvent() is an inherently dangerous action, as it allows event data to be irreversibly altered. Use
caution when using this functionality in your component. At an absolute minimum, consider adding a confirmation window for
your users that clearly states the outcome of the action, with an option for them to cancel if they wish.
Warning: Using removeEvent() is an inherently dangerous action, as it allows event data to be irreversibly altered. Use
caution when using this functionality in your component. At an absolute minimum, consider adding a confirmation window for
your users that clearly states the outcome of the action, with an option for them to cancel if they wish.
66
Use Mobile Device Features in Mobile Apps CalendarService Example
SEE ALSO:
Lightning Web Components Developer Guide: CalendarService API
CalendarService Example
CalendarService Example
Here’s a basic example of a Lightning web component that displays calendar events and allows the user to perform basic calendar-related
functions.
The component’s HTML template is minimal, with a “main” display view that lists calendar events and a “detail” display view that shows
an event’s details.
<template>
<!-- Main View -->
<template if:false={detailViewIsOpen}>
<lightning-card title="Today's Events" icon-name="utility:dayview">
<template for:each={todayEvents} for:item="item">
<div class="slds-var-p-horizontal_medium slds-var-p-vertical_x-small"
key={item.id} onclick={showDetailView} data-id={item.id}>
<p class="slds-text-heading_small"><b>{item.title}</b></p>
<p class="slds-text-heading_small">{item.startTimeDisplay} —
{item.endTimeDisplay}</p>
</div>
</template>
</lightning-card>
</template>
67
Use Mobile Device Features in Mobile Apps CalendarService Example
<lightning-menu-item prefix-icon-name="utility:edit"
value="Update" label="Update in Device Calendar"
onclick={updateCalendarEvent}></lightning-menu-item>
<lightning-menu-item prefix-icon-name="utility:delete"
value="Delete" label="Remove from Device Calendar"
onclick={deleteCalendarEvent}></lightning-menu-item>
</lightning-button-menu>
</td>
</tr>
<tr>
<td colspan="3">
<ul class="slds-has-dividers_bottom-space">
<li class="slds-item">
<span
class="slds-text-heading_small"><b>{selectedItem.title}</b></span><br>
<span
class="slds-text-heading_small">{selectedItem.startTimeDisplay} —
{selectedItem.endTimeDisplay}</span>
</li>
<li class="slds-item">
<span
class="slds-text-heading_small">Reminders</span><br>
<template for:each={selectedItem.alarmsDisplay}
for:item="alarm">
<span class="slds-text-body_regular"
key={alarm}>{alarm}<br></span>
</template>
</li>
<li class="slds-item">
<span
class="slds-text-heading_small">Location</span><br>
<span
class="slds-text-body_regular">{selectedItem.location}</span>
</li>
<li class="slds-item">
<span
class="slds-text-heading_small">Attendees</span><br>
<template for:each={selectedItem.attendees}
for:item="attendee">
<span class="slds-text-body_regular"
key={attendee.name}>{attendee.name} ({attendee.email})<br></span>
</template>
</li>
<li class="slds-item">
<span class="slds-text-heading_small">Notes</span><br>
68
Use Mobile Device Features in Mobile Apps CalendarService Example
<span
class="slds-text-body_regular">{selectedItem.notes}</span>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
</template>
</template>
This example simply uses CalendarService to display events, and allows you to perform simple actions on calendar items. A status message
is returned when there’s an error. In this example, the events are hard-coded, rather than fetched via API calls from a Salesforce org.
You’ll need to build functionality to fetch event data from your Salesforce org as part of your component.
todayEvents = [];
detailViewIsOpen = false;
selectedItem = null;
selectedItemIndex = -1;
calendarPermissionRationaleText = "Allow access to your calendar to enable calendar
event processing.";
calendarService;
connectedCallback() {
console.log("Start connected callback");
try {
this.calendarService = getCalendarService();
this.todayEvents = this.getTodayEvents();
this.todayEvents.forEach(item => this.generateDisplayFields(item));
console.log(`End connected callback with ${this.todayEvents.length} events for
today.`);
} catch (err) {
console.log(`connectedCallback failed with error: ${err}`);
}
}
showDetailView(event) {
const id = event.currentTarget.dataset.id;
this.selectedItemIndex = this.todayEvents.findIndex(item => item.id === id);
if (this.selectedItemIndex != -1) {
this.selectedItem = this.todayEvents[this.selectedItemIndex];
} else {
this.selectedItem = null;
}
69
Use Mobile Device Features in Mobile Apps CalendarService Example
hideDetailView() {
this.detailViewIsOpen = false;
this.selectedItem = null;
this.selectedItemIndex = -1;
}
addCalendarEvent() {
if (this.calendarService.isAvailable() && this.selectedItemIndex != -1 &&
this.selectedItem) {
const options = {
"permissionRationaleText" : this.calendarPermissionRationaleText
};
console.log(`options: ${JSON.stringify(options)}`);
console.log(`Adding selectedItem: ${JSON.stringify(this.selectedItem)}`);
this.calendarService.addEvent(this.selectedItem, options)
.then((sanitizedEvent) => {
this.generateDisplayFields(sanitizedEvent);
this.selectedItem = sanitizedEvent;
this.todayEvents[this.selectedItemIndex] = sanitizedEvent;
this.showSuccessAlert("Add Event", "Event was added successfully to the
device default calendar.");
console.log(`sanitizedEvent: ${JSON.stringify(sanitizedEvent)}`);
})
.catch((error) => {
console.error(error);
this.showFailureAlert("Add Event", `There was a problem adding the event
to the device default calendar: ${error.message}`);
});
} else {
console.log("Calendar Service Is Not Available");
this.showFailureAlert("Add Event", "Calendar Service is not available.");
}
}
updateCalendarEvent() {
if (this.calendarService.isAvailable() && this.selectedItemIndex != -1 &&
this.selectedItem) {
const options = {
"permissionRationaleText" : this.calendarPermissionRationaleText,
"span" : "ThisEvent"
};
console.log(`options: ${JSON.stringify(options)}`);
70
Use Mobile Device Features in Mobile Apps CalendarService Example
this.calendarService.updateEvent(this.selectedItem, options)
.then((sanitizedEvent) => {
this.generateDisplayFields(sanitizedEvent);
this.selectedItem = sanitizedEvent;
this.todayEvents[this.selectedItemIndex] = sanitizedEvent;
this.showSuccessAlert("Update Event", "Event was updated successfully in
the device default calendar.");
console.log(`sanitizedEvent: ${JSON.stringify(sanitizedEvent)}`);
})
.catch((error) => {
console.error(error);
this.showFailureAlert("Update Event", `There was a problem updating the
event in the device default calendar: ${error.message}`);
});
} else {
console.log("Calendar Service Is Not Available");
this.showFailureAlert("Update Event", "Calendar Service is not available.");
}
}
deleteCalendarEvent() {
if (this.calendarService.isAvailable() && this.selectedItemIndex != -1 &&
this.selectedItem) {
LightningConfirm.open(
{
label: "Delete Event",
message: "Are you sure you want to delete this event?",
theme: "warning"
}
).then((response) => {
if (response === true) {
const options = {
"permissionRationaleText" : this.calendarPermissionRationaleText,
"span" : "ThisEvent"
};
console.log(`options: ${JSON.stringify(options)}`);
console.log(`Deleting selectedItem:
${JSON.stringify(this.selectedItem)}`);
this.calendarService.removeEvent(this.selectedItem, options)
.then(() => {
this.todayEvents.splice(this.selectedItemIndex, 1);
this.hideDetailView();
this.showSuccessAlert("Delete Event", "Event was removed successfully
from the device default calendar.");
})
.catch((error) => {
console.error(error);
this.showFailureAlert("Delete Event", `There was a problem removing
the event from the device default calendar: ${error.message}`);
71
Use Mobile Device Features in Mobile Apps CalendarService Example
});
}
});
} else {
console.log("Calendar Service Is Not Available");
this.showFailureAlert("Delete Event", "Calendar Service is not available.");
}
}
getTodayEvents() {
// For this sample code, we've hard-coded some made-up values.
// Your component should fetch events from your SF org and convert them to the
following object format.
const events = [
{
id: "event_id_1", // will be overwritten after a call to
calendarService.addEvent()
isAllDay: false,
startDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(8, 0, 0), // 8 AM
endDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(10, 0, 0), // 10 AM
availability: "Busy",
status: "Confirmed",
calendarId: null, // will be assigned to the default device calendar
title: "Team Meeting",
location: "3514 Ruckman Road, San Francisco, CA 94105",
notes: "Discussing customer request for new calendar feature",
alarms: [{relativeOffsetSeconds: 600}], // 10 mins before event
attendees: [
{ name: "Jamal Booker", email: "[email protected]", role:
"Required", status: "Accepted" },
{ name: "Robert Bullard", email: "[email protected]",
role: "Required", status: "Pending" },
{ name: "Gordon Chu", email: "[email protected]", role:
"Optional", status: "Declined" },
],
recurrenceRules: null
},
{
id: "event_id_2", // will be overwritten after a call to
calendarService.addEvent()
isAllDay: false,
startDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(10, 30, 0), // 10:30
AM
endDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(11, 0, 0), // 11 AM
availability: "Busy",
status: "Confirmed",
calendarId: null, // will be assigned to the default device calendar
title: "Quarterly Review",
location: "2135 Alpha Avenue, Fernandina Beach, FL 32034",
notes: "Reviewing results of Q2 and planning Q3",
alarms: [{relativeOffsetSeconds: 1800}], // 30 mins before event
attendees: [
{ name: "Alex Driskel", email: "[email protected]", role:
"Required", status: "Accepted" },
72
Use Mobile Device Features in Mobile Apps CalendarService Example
73
Use Mobile Device Features in Mobile Apps CalendarService Example
recurrenceRules: null
},
{
id: "event_id_5", // will be overwritten after a call to
calendarService.addEvent()
isAllDay: false,
startDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(14, 30, 0), // 2:30
PM
endDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(15, 30, 0), // 3:30
PM
availability: "Tentative",
status: "Tentative",
calendarId: null, // will be assigned to the default device calendar
title: "Sales Workgroup",
location: "3270 Armbrester Drive, Gardena, CA 90248",
notes: "Discuss the new customer opportunities",
alarms: [{relativeOffsetSeconds: 1800}], // 30 mins before event
attendees: [
{ name: "Raul Nieto", email: "[email protected]", role:
"Required", status: "Accepted" },
{ name: "Salome Ofodu", email: "[email protected]", role:
"Required", status: "Tentative" },
{ name: "Justus Pardo", email: "[email protected]", role:
"Required", status: "Tentative" },
{ name: "Gorav Patel", email: "[email protected]", role:
"Required", status: "Pending" },
],
recurrenceRules: null
},
{
id: "event_id_6", // will be overwritten after a call to
calendarService.addEvent()
isAllDay: false,
startDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(15, 30, 0), // 3:30
PM
endDateSecondsUTC: this.getTodayTimestampAtTimeOfDay(17, 30, 0), // 5:30
PM
availability: "Busy",
status: "Confirmed",
calendarId: null, // will be assigned to the default device calendar
title: "Executive Team",
location: "56 Main Street, Seattle, WA 98119",
notes: "Report on Q2 sales and new leads",
alarms: [{relativeOffsetSeconds: 600}, {relativeOffsetSeconds: 3600}], //
10 mins and 1 hour before event
attendees: [
{ name: "Florentina Perez", email: "[email protected]", role:
"Required", status: "Accepted" },
{ name: "Harryette Randall", email: "[email protected]",
role: "Required", status: "Accepted" },
{ name: "Sofia Rivera", email: "[email protected]", role:
"Required", status: "Accepted" },
],
recurrenceRules: null
74
Use Mobile Device Features in Mobile Apps CalendarService Example
}
];
return events;
}
timeOfDayToString(dateSecondsUTC) {
let d = new Date(dateSecondsUTC * 1000); // seconds to milliseconds
let ampm = "AM";
let str = "";
if (d.getMinutes() > 0) {
if (d.getMinutes() < 10) {
str += `:0${d.getMinutes()}`;
} else {
str += `:${d.getMinutes()}`;
}
}
str += ` ${ampm}`;
return str;
}
alarmsToString(alarms) {
let results = [];
if (alarms) {
alarms.forEach(alarm => {
if (alarm.relativeOffsetSeconds == 0) {
results.push("At time of event");
} else {
const mins = parseInt(Math.ceil(Math.abs(alarm.relativeOffsetSeconds)
/ 60.0));
if (mins == 1) {
results.push("1 minute before");
} else if (mins < 60) {
results.push(`${mins} minutes before`);
} else {
const hours = parseInt(Math.ceil(mins / 60.0));
if (hours == 1) {
75
Use Mobile Device Features in Mobile Apps CalendarService Example
return results;
}
generateDisplayFields(calendarEvent) {
// these are used for display purpose only
calendarEvent.startTimeDisplay =
this.timeOfDayToString(calendarEvent.startDateSecondsUTC);
calendarEvent.endTimeDisplay =
this.timeOfDayToString(calendarEvent.endDateSecondsUTC);
calendarEvent.alarmsDisplay = this.alarmsToString(calendarEvent.alarms);
}
showSuccessAlert(title, message) {
LightningAlert.open(
{
message: message,
theme: "success",
label: title,
}
);
}
showFailureAlert(title, message) {
console.log(`calendarService.isAvailable(): ${this.calendarService.isAvailable()}`);
console.log(`selectedItemIndex: ${this.selectedItemIndex}`);
console.log(`selectedItem: ${this.selectedItem.id}`);
LightningAlert.open(
{
message: message,
theme: "error", // a red theme intended for error states
label: title,
}
);
}
76
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
SEE ALSO:
Use the CalendarService API
77
Use Mobile Device Features in Mobile Apps Access Contacts on a Mobile Device
In previous versions of Android, users would see the system permissions dialog each time the app requested permission unless the
user had previously selected “don’t ask again”. This change in Android 11 discourages repeated requests for permissions that users
have chosen to deny.
If the user has denied permission to access the Contacts app and needs to change their permissions to allow access, they can do so
in their device’s settings.
Development Considerations
You can certainly develop the user experience for your component on a desktop or laptop development system. But be sure to test
calendar and event functionality on the physical devices on which you plan to deploy your Lightning app.
Important: CalendarService allows for actions that, if used irresponsibly or incorrectly, can lead to irreversible consequences on
your users’ devices. These dangerous actions include altering and deleting calendar events.
As with all mobile capabilities, implementation of CalendarService’s functionality, dangerous actions included, is at your discretion.
Use caution when using dangerous actions in your component.
CalendarService Considerations
CalendarService is built on top of mobile operating system and device features. CalendarService’s capabilities therefore depend on
Android or iOS features, which are subject to change beyond our control. When mobile operating system features change, the behavior
of CalendarService can change without notice.
Important: ContactsService does not and cannot function when running in a web browser, whether on a desktop or mobile
device.
IN THIS SECTION:
ContactsService User Experience
Your component can deliver any user experience you desire, but there’s a common flow for any component that imports or processes
contact data.
Use the ContactsService API
To develop a Lightning web component with contacts-based features, use the ContactsService API as your method for selecting
contacts from a device’s address book.
ContactsService Example
Here’s a minimal but complete example of a Lightning web component that uses ContactsService to select on-device contacts and
then process the contact data in the component.
Compatibility and Requirements
ContactsService is a JavaScript module that provides an API to Lightning web components to make mobile hardware and platform
(operating system) features available in JavaScript. It requires access to device hardware and device platform APIs. This access is
only available when ContactsService runs within a compatible Salesforce mobile app. It does not and cannot function when
running in a standard web browser, whether the browser runs on a desktop or mobile device.
78
Use Mobile Device Features in Mobile Apps ContactsService User Experience
SEE ALSO:
Lightning Web Components Developer Guide: ContactsService API
3. After the desired contacts are selected, tap the “check” icon or Done button to continue.
79
Use Mobile Device Features in Mobile Apps Use the ContactsService API
4. Your Lightning web component receives the data from the selected contacts. Your component can display additional user interface
controls to further process the contacts, add the contacts to Salesforce, or otherwise apply whatever custom logic your business
process requires.
After it’s imported into your component, use the factory function to get an instance of ContactsService. With your ContactsService
instance, use the utility functions and constants to verify availability. Then use contacts-related functions to select contacts from the
device.
80
Use Mobile Device Features in Mobile Apps Use the ContactsService API
See getContacts(options) for more details about how to handle contacts data, handle errors, and so on.
SEE ALSO:
Lightning Web Components Developer Guide: ContactsService API
ContactsService Example
81
Use Mobile Device Features in Mobile Apps ContactsService Example
ContactsService Example
Here’s a minimal but complete example of a Lightning web component that uses ContactsService to select on-device contacts and then
process the contact data in the component.
The component’s HTML template is minimal, with a button to start selecting contacts, and a place to display results.
<!-- contactsServiceExample.html -->
<template>
</template>
Note the use of the for:each directive and nested template tag to iterate through the list of contacts, and a further nested
for:each directive and template to iterate through each contact’s list of phone numbers. You can do the same for email addresses,
IM handles, and other contact details.
82
Use Mobile Device Features in Mobile Apps ContactsService Example
This example doesn’t import contacts into Salesforce, or otherwise use the contacts data provided from the device. It simply uses
ContactsService to allow you to select contacts on the device, and then displays the returned contact data, or a status message when
there’s an error.
// contactsServiceExample.js
import { LightningElement } from 'lwc';
import { getContactsService } from 'lightning/mobileCapabilities';
handleImportContacts() {
83
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
SEE ALSO:
Use the ContactsService API
Lightning Web Components Developer Guide: Render Lists
84
Use Mobile Device Features in Mobile Apps Considerations and Limitations
• ContactsService requires the use of the mobile device’s contacts. Your user must grant your app access to contacts. The exact user
experience is governed by the platform. The request happens automatically on first use, and is managed by the device itself, but
you should plan for it when designing the user experience of your app.
• In Android 11 or later, if the user taps “Deny” for permission to access the Contacts app more than once during the app’s lifetime of
installation on a device, the user won’t see the system permissions dialog again. Tapping Deny multiple times implicitly chooses the
“don’t ask again” option.
In previous versions of Android, users would see the system permissions dialog each time the app requested permission unless the
user had previously selected “don’t ask again”. This change in Android 11 discourages repeated requests for permissions that users
have chosen to deny.
If the user has denied permission to access the Contacts app and needs to change their permissions to allow access, they can do so
in their device’s settings.
• If Mobile Device Management (MDM) is in use on a device, and MDM restricts access to contacts data, ContactsService can’t access
it.
• If the user doesn't have any contacts in their device’s contact list, ContactsService won’t work.
• If the user has contacts associated with specific accounts on their device, those accounts must have contacts sync enabled in order
for ContactsService to access them. In other words, ContactsService can only access contacts that are visible in your user’s device’s
native contact list. See Use other contact accounts on iPhone (iOS) and Back up & sync device contacts (Android) for more information.
If you’re having trouble getting ContactsService to access contact data, try the following:
• First, verify that your device contact list contains the contact data you’re trying to access. ContactsService can only access contacts
that are visible in your device’s native contact list.
• Next, verify that you’ve granted contacts permission to the mobile app where your component is running. You can check this in
your device’s settings.
• Finally, double-check the configuration of ContactsService in your code.
Development Considerations
Virtual devices might not have any contact data when they’re created. To test ContactsService on a virtual device, you’ll first need to
create some contact records in the virtual device’s Contacts app. Alternatively, you can import contact data in the standard .vcf format,
or sign into a real Google or iCloud account that has contact data associated with it.
You can certainly develop the user experience for your component on a desktop or laptop development system. But be sure to test
contact access functionality on the physical devices on which you plan to deploy your Lightning app.
ContactsService Considerations
85
Use Mobile Device Features in Mobile Apps Scan Documents on a Mobile Device
Be aware of the following considerations when using ContactsService in your Lightning app.
• ContactsService is built on top of mobile operating system and device features. ContactsService’s capabilities therefore depend on
Android or iOS features, which are subject to change beyond our control. When mobile operating system features change, the
behavior of ContactsService can change without notice.
• A Lightning component that uses ContactsService can have a custom user interface in the component itself. However, the contacts
selection user interface can’t be customized.
Important: DocumentScanner does not and cannot function when running in a web browser, whether on a desktop or mobile
device.
IN THIS SECTION:
Use the DocumentScanner API
To add document scanning features to a Lightning web component, use the DocumentScanner API.
DocumentScanner Example
Here’s an example of a Lightning web component that uses DocumentScanner to capture text data from an image.
Compatibility and Requirements
DocumentScanner is a JavaScript module that provides an API to Lightning web components to make mobile hardware and platform
(operating system) features available in JavaScript. It requires access to device hardware and device platform APIs. This access is
only available when DocumentScanner runs within a compatible Salesforce mobile app. It does not and cannot function when
running in a standard web browser, whether the browser runs on a desktop or mobile device.
Considerations and Limitations
Consider these guidelines and limitations when developing features that use the DocumentScanner API.
86
Use Mobile Device Features in Mobile Apps Use the DocumentScanner API
After it’s imported into your component, use the factory function to get an instance of DocumentScanner. With your DocumentScanner
instance, use the utility functions and constants to verify availability. Then use the scan function to initiate a document scan.
Scan a Document
Scanning documents with DocumentScanner is straightforward.
• Start a scan with scan(options).
• (Your user scans a document.)
• Handle the result of the scan, which is returned in the form of a promise.
For example:
myScanner
.scan(scanningOptions)
.then((result) => {
// Do something with the result of the scan
console.log(result);
this.scannedDocument = result.value;
})
.catch((error) => {
// Handle cancellation and scanning errors here
console.error(error);
});
When scanning is successful, the returned promise contains the string value of the scanned text. See (reference doc link) for the structure
and contents of the result.
If scanning is unsuccessful, the promise is returned as an error, which includes an error code and message that you can use in error
handling. See DocumentScanner API in the Lightning Web Components Developer Guide for more information.
87
Use Mobile Device Features in Mobile Apps DocumentScanner Example
DocumentScanner Example
Here’s an example of a Lightning web component that uses DocumentScanner to capture text data from an image.
There’s an option to select the source of the image to be scanned, from either the device camera or the device image library.
<template>
<table class="rootTable">
<tbody>
<lightning-button
variant="brand"
label="Camera"
title="Capture document with camera"
onclick={handleScanFromCameraClick}>
</lightning-button>
<lightning-button
variant="brand"
label="Photo Library"
title="Scan document from photo library"
onclick={handleScanFromPhotoLibraryClick}
class="slds-var-m-left_x-small">
</lightning-button>
</div>
88
Use Mobile Device Features in Mobile Apps DocumentScanner Example
<template if:true={scannedDocument}>
// results of the scan are displayed here
<div class="slds-var-p-around_medium">
Text Recognition Result: <br/><br/>
{scannedDocument.text}
</div>
</template>
</lightning-card>
</td>
</tr>
</div>
</template>
</td>
</tr>
</tbody>
</table>
</template>
This example uses DocumentScanner to choose a source for the document to be scanned, and to perform a basic scanning operation.
After the scan completes, the results are displayed, along with an SVG graphic that annotates the scanned document graphic with an
overlay of the result structured text data. A status message is returned when there’s an error.
import { LightningElement } from "lwc";
import { getDocumentScanner } from "lightning/mobileCapabilities";
handleScanFromCameraClick() {
this.scanDocument("DEVICE_CAMERA");
}
handleScanFromPhotoLibraryClick() {
89
Use Mobile Device Features in Mobile Apps DocumentScanner Example
this.scanDocument("PHOTO_LIBRARY");
}
scanDocument(imageSource) {
// Clear previous results / errors
this.resetScanResults();
resetScanResults() {
this.scannedDocument = null;
this.scannerError = null;
}
processScannedDocuments(documents) {
// DocumentScanner only processes the first scanned document in an array
this.scannedDocument = documents[0];
// And this is where you take over; process results as desired
}
90
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
let svg =
`<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ` +
`xmlns:xlink="http://www.w3.org/1999/xlink" ` +
`width="${width}" height="${height}" viewBox="0, 0, ${nWidth}, ${nHeight}">`;
textBlocks.forEach((block) =>
block.lines.forEach((line) =>
line.elements.forEach((element) => {
const frame = element.frame;
svg +=
`<rect x="${frame.x}" y="${frame.y}" width="${frame.width}" ` +
`height="${frame.height}" style="fill:green;fill-opacity:0.5" />`;
})
)
);
svg += "</svg>";
91
Use Mobile Device Features in Mobile Apps Considerations and Limitations
• DocumentScanner doesn’t implement scanning itself. Instead, it delegates document scanning and recognition to an underlying
SDK implemented in native code (Android or iOS). While the features provided by DocumentScanner are the same across both
platforms, they’re subject to some platform-specific quirks and minor differences.
– If the chosen input for the document to be scanned is the device camera, DocumentScanner automatically uses the “main”
device camera. Built-in controls allow choosing other device cameras, if available.
– If you can’t get a clear picture of the document, it can’t be recognized. The quality of the device camera affects text recognition.
A damaged or low-quality camera lens or focusing system, poor lighting, motion, and other factors can make it difficult or
impossible to get a clear picture of a document.
– The quality of the document affects text recognition. Specifically, documents with damaged or obscured text are hard to recognize
successfully.
– DocumentScanner recognizes machine printed text, not handwriting. While DocumentScanner is capable of performing text
recognition on a variety of typefaces, highly stylized fonts can lower recognition accuracy.
Development Considerations
• DocumentScanner requires access to camera hardware, or to the device photo library. To test scanning using a camera during
development, use actual, physical devices.
– The Android emulator can simulate camera hardware by using a webcam on your development system. To do so, edit the camera
configuration for your Android Virtual Device, in the advanced settings panel. However, the camera built into most laptops is
much lower quality than what’s found on modern mobile phones. A low-quality camera limits the usefulness of testing text
recognition.
– The iOS simulator doesn’t provide access to simulated camera hardware at all. You can certainly develop the user experience
for your component on a desktop or laptop development system. But, be sure to test camera scanning functionality on the
physical devices on which you plan to deploy your Lightning app.
• As a work-around for limited camera access in virtual devices, you can load a few sample images into the virtual device’s photo
library, and use those for scanning operations. However, if you expect your users to scan using a device camera, be sure to also test
using real device cameras.
DocumentScanner Considerations
92
Use Mobile Device Features in Mobile Apps Use Location on a Mobile Device
DocumentScanner is built on top of mobile operating system and device features. DocumentScanner’s capabilities therefore depend
on Android or iOS features, which are subject to change beyond our control. When mobile operating system features change, the
behavior of DocumentScanner can change without notice.
Important: LocationService does not and cannot function when running in a web browser, whether running on a desktop or
mobile device.
LocationService provides coordinate data only: latitude, longitude, altitude, and some motion details. It doesn’t include derived data,
such as a physical address or map detail. If you’re using the location information to, for example, show a position on a map, you might
need a network connection to receive map data, such as map tiles, and so on.
IN THIS SECTION:
LocationService User Experience
Your component can deliver any user experience you desire. There are a number of common location-based features where
LocationService might be suitable.
Location Basics
On the surface, the concept of location is a simple one. Where am I? Where is Salesforce Tower? How do I get to Salesforce Tower
from where I am right now? These are all location-based features, and we’ve been using them on mobile devices for many years.
As a developer, the concept of location can be more complex.
Use the LocationService API
To develop a Lightning web component with location-based features, use the LocationService API to determine the current location.
LocationService Example
Here’s a basic example of a Lightning web component that gets the user’s current location and displays it on a map.
Compatibility and Requirements
LocationService is a JavaScript module that provides an API to Lightning web components to make mobile hardware and platform
(operating system) features available in JavaScript. LocationService requires access to device hardware and device platform APIs.
This access is only available when LocationService runs within a compatible Salesforce mobile app. It does not and cannot function
when running in a standard web browser, whether the browser runs on a desktop or mobile device.
Considerations and Limitations
Keep the following in mind when developing features that use the LocationService API.
SEE ALSO:
Lightning Web Components Developer Guide: LocationService API
93
Use Mobile Device Features in Mobile Apps LocationService User Experience
Location Basics
On the surface, the concept of location is a simple one. Where am I? Where is Salesforce Tower? How do I get to Salesforce Tower from
where I am right now? These are all location-based features, and we’ve been using them on mobile devices for many years. As a developer,
the concept of location can be more complex.
Location itself can be reduced to basic X,Y coordinates: a latitude and longitude, also known as a geolocation. For example,
{37.7898007,-122.3991439} (the location of Salesforce HQ). But knowing the coordinates of Salesforce Tower doesn’t show
you where it is on a map, or tell you where you are in relation to it, or how to get there. These are location-based features, but simple
location is not enough to build them. It also requires map rendering, geocoding of street addresses, and route calculation, among other
things.
LocationService is a simple API, with features inspired by the similar Geolocation API available in web browsers. It provides a straightforward
mechanism for getting the current geolocation of the physical device on which it runs. That’s it. For basic map display, combine
LocationService with the lightning-map component. For more complex mapping solutions, consider adding third-party libraries
and services, such as Google Maps or Leaflet.
94
Use Mobile Device Features in Mobile Apps Use the LocationService API
After it’s imported into your component, use the factory function to get an instance of LocationService. With your LocationService
instance, use the isAvailable() utility function to verify availability. Use the location calculation functions to get the current
location, or to configure and receive location change updates.
See getCurrentPosition(options) for more details for configuration, results format, and error handling.
95
Use Mobile Device Features in Mobile Apps LocationService Example
myLocationWatchId = 0;
async startTracking() {
let locationService = getLocationService();
this.myLocationWatchId = await locationService.
startWatchingPosition({ enableHighAccuracy:true }, (result, error) => {
See startWatchingPosition(options, callback) for additional usage details, including important resource allocation
notes. See stopWatchingPosition(watchId) for an example stopTracking() function.
SEE ALSO:
Lightning Web Components Developer Guide: LocationService API
LocationService Example
LocationService Example
Here’s a basic example of a Lightning web component that gets the user’s current location and displays it on a map.
The HTML template provides the bare minimum for a location-based interface. There’s an element to display the map, a bit of static help
text, and a button to get the location. There are two interesting aspects of this template:
• Disabling the Get Current Location button using the disabled attribute when not in a supported Salesforce mobile app. This
attribute is set based on the results of isAvailable() when the component is initialized.
• A spinner that indicates “indeterminate progress” while waiting for the current location request to resolve.
<!-- locationServiceExample.html -->
<template>
<div class="slds-text-align_center">
<span class="slds-text-heading_large">Where in the World Am I?</span>
</div>
96
Use Mobile Device Features in Mobile Apps LocationService Example
Once the current location is determined, we use the lightning-map base component to display it. Each phase of the location
request lifecycle writes a console message.
// locationServiceExample.js
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { getLocationService } from 'lightning/mobileCapabilities';
97
Use Mobile Device Features in Mobile Apps LocationService Example
myLocationService;
currentLocation;
locationButtonDisabled = false;
requestInProgress = false;
handleGetCurrentLocationClick(event) {
// Reset current location
this.currentLocation = null;
this.dispatchEvent(
new ShowToastEvent({
title: 'Location Detected',
message: 'Location determined successfully.',
variant: 'success'
})
);
})
.catch((error) => {
// Handle errors here
console.error(error);
98
Use Mobile Device Features in Mobile Apps LocationService Example
// Let user know they need to use a mobile phone with a GPS
this.dispatchEvent(
new ShowToastEvent({
title: 'LocationService Is Not Available',
message: 'Try again from the Salesforce app on a mobile device.',
variant: 'error'
})
);
}
}
SEE ALSO:
Use the LocationService API
99
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
• Location tracking is subject to significant privacy, processing, and power use restrictions, imposed by the underlying platform (Android
or iOS). See important details in the LocationService API reference documentation.
• Many factors affect the accuracy of location detection, the speed of determining the current location, and how much impact location
tracking has on battery life.
100
Use Mobile Device Features in Mobile Apps Interact with NFC Tags on a Mobile Device
• Mobile devices vary in the quality of the location detection they provide.
• If a mobile device can’t determine its location, neither can LocationService. The quality of the device’s positioning hardware, tall or
dense buildings, indoor use, and other external factors can reduce the accuracy of location determination.
• Location tracking on high accuracy can significantly increase power use, which affects how quickly a mobile device drains its
battery.
If you’re having trouble getting LocationService to provide an accurate location, try the following:
• First, verify that the device is able to determine its location. If the standard Maps app can’t get an accurate location, neither can
LocationService.
• Next, verify that the user has granted location access to the mobile app where your component is running.
• Finally, double-check the configuration of LocationService in your code. In particular, verify that you’ve set the accuracy level as
needed for your component’s features.
Development Considerations
LocationService requires access to positioning hardware, such as GPS, Wi-Fi, cellular, and other location-detection hardware of your
mobile device. To test location services during development, use actual, physical devices when possible.
• The Android emulator and iOS simulator can each be configured to provide simulated location details.
• Neither virtual device accurately simulates location detection in the real world, especially for environments where location detection
is challenging.
You can certainly develop the user experience for your component on a desktop or laptop development system. But be sure to test
location-based functionality on the physical devices on which you plan to deploy your Lightning app.
LocationService Considerations
Be aware of the following considerations when using LocationService in your Lightning app.
• LocationService is built on top of mobile operating system and device features. LocationService’s location capabilities therefore
depend on Android or iOS features, which are subject to change beyond our control. When mobile operating system features change,
the behavior of LocationService can change without notice.
• LocationService doesn’t provide map data. To display the current location on a map, you need to add extra functionality, for example,
to retrieve map tile graphics.
• LocationService detects a device’s current location only. While you can receive updates when the current location changes, updates
provide only the new location. If needed, perform distance, proximity, or geofencing calculations yourself, in your own JavaScript.
Important: While it’s possible and not too difficult, a manually implemented geofencing feature can result in severe battery
drain on devices that use it.
Important: NFCService does not and cannot function when running in a web browser, whether on a desktop or mobile device.
101
Use Mobile Device Features in Mobile Apps NFCService User Experience
IN THIS SECTION:
NFCService User Experience
Your component can deliver any user experience you desire, but there’s a common flow for any component that interacts with NFCs.
Use the NFCService API
To develop a Lightning web component capable of interacting with NFCs, use the NFCService API.
NFCService Example
Here’s a basic example of a Lightning web component that uses NFCService to parse text data from an image.
Compatibility and Requirements
NFCService is a JavaScript module that provides an API to Lightning web components to make mobile hardware and platform
(operating system) features available in JavaScript. It requires access to device hardware and device platform APIs. This access is
only available when NFCService runs within a compatible Salesforce mobile app. It does not and cannot function when running
in a standard web browser, whether the browser runs on a desktop or mobile device.
Considerations and Limitations
Consider these guidelines and limitations when developing features that use the NFCService API.
After it’s imported into your component, use the factory function to get an instance of NFCService. With your NFCService instance, use
the utility functions and constants to verify availability. Then use NFC-related functions to perform the associated functionality.
102
Use Mobile Device Features in Mobile Apps Use the NFCService API
myNFCService
.erase(options)
.then((successMessage) => {
// Receive a success message following a successful erase operation
console.log(successMessage);
})
.catch((error) => {
// Handle cancellation and erase errors here
103
Use Mobile Device Features in Mobile Apps NFCService Example
console.error(error);
});
Note: The erase() function can only be performed on writable NFC tags. Attempting this function on a read-only NFC tag
results in an error.
myNFCService
.write(options)
.then((successMessage) => {
// Receive a success message following a successful write operation
console.log(successMessage);
})
.catch((error) => {
// Handle cancellation and write errors here
console.error(error);
});
Note: The write() function can only be performed on writable NFC tags. Attempting this function on a read-only NFC tag
will result in an error.
NFCService Example
Here’s a basic example of a Lightning web component that uses NFCService to parse text data from an image.
The component’s HTML template is minimal, with a display view that includes three buttons, one each for read, erase, and write operations.
<template>
<lightning-card title="NFC Service Demo" icon-name="custom:phone_portrait">
<div class="slds-var-m-around_medium">
Choose an action to perform on an NFC tag:<br><br>
<lightning-button
variant="brand"
label="Read"
title="Read the content of an NFC tag"
onclick={handleReadClick}>
</lightning-button>
<lightning-button
variant="brand"
label="Erase"
title="Erase the content of an NFC tag"
onclick={handleEraseClick}
class="slds-var-m-left_x-small">
</lightning-button>
<lightning-button
variant="brand"
104
Use Mobile Device Features in Mobile Apps NFCService Example
label="Write"
title="Write sample content to an NFC tag"
onclick={handleWriteClick}
class="slds-var-m-left_x-small">
</lightning-button>
</div>
<div class="slds-var-m-around_medium">
<lightning-formatted-text value={status}></lightning-formatted-text>
</div>
</lightning-card>
</template>
This example uses NFCService to select the NFC operation to be performed, performs the operation, and displays a success message
when completed successfully. An error message is returned when there’s an error.
import { LightningElement } from 'lwc';
import { getNfcService } from 'lightning/mobileCapabilities';
connectedCallback() {
this.nfcService = getNfcService();
}
handleReadClick() {
if(this.nfcService.isAvailable()) {
const options = {
"instructionText": "Hold your phone near the tag to read.",
"successText": "Tag read successfully!"
};
this.nfcService.read(options)
.then((result) => {
// Do something with the result
this.status = JSON.stringify(result, undefined, 2);
})
.catch((error) => {
// Handle errors
this.status = 'Error code: ' + error.code + '\nError message: ' + error.message;
});
} else {
// service not available
this.status = 'Problem initiating NFC service. Are you using a mobile device?';
}
}
handleEraseClick() {
if(this.nfcService.isAvailable()) {
const options = {
"instructionText": "Hold your phone near the tag to erase.",
"successText": "Tag erased successfully!"
};
this.nfcService.erase(options)
105
Use Mobile Device Features in Mobile Apps NFCService Example
.then(() => {
this.status = "Tag erased successfully!";
})
.catch((error) => {
// Handle errors
this.status = 'Error code: ' + error.code + '\nError message: ' + error.message;
});
} else {
// service not available
this.status = 'Problem initiating NFC service. Are you using a mobile device?';
}
}
async handleWriteClick() {
if(this.nfcService.isAvailable()) {
const options = {
"instructionText": "Hold your phone near the tag to write.",
"successText": "Tag written successfully!"
};
const payload = await this.createWritePayload();
this.nfcService.write(payload, options)
.then(() => {
this.status = "Tag written successfully!";
})
.catch((error) => {
// Handle errors
this.status = 'Error code: ' + error.code + '\nError message: ' + error.message;
});
} else {
// service not available
this.status = 'Problem initiating NFC service. Are you using a mobile device?';
}
}
async createWritePayload() {
// Here we demonstrate how you can write several records to an NFC tag.
// Consider the scenario where you want to write the content of a business card
// to an NFC tag. The content can be broken down into a number of text and uri
records.
const nameRecord = await this.nfcService.createTextRecord({text: "John Smith", langId:
"en"});
const phone1Record = await this.nfcService.createTextRecord({text: "(123) 456-7890
Office", langId: "en"});
const phone2Record = await this.nfcService.createTextRecord({text: "(321) 654-0987
Direct", langId: "en"});
const emailRecord = await
this.nfcService.createUriRecord("mailto:[email protected]");
const addressRecord = await this.nfcService.createTextRecord({text: "584 South Paris
Hill Ave., Lancaster, CA 93535", langId: "en"});
const websiteRecord = await
this.nfcService.createUriRecord("https://www.mycompany.com");
return [nameRecord, phone1Record, phone2Record, emailRecord, addressRecord,
106
Use Mobile Device Features in Mobile Apps Compatibility and Requirements
websiteRecord];
}
}
Warning: NFCService allows for an action that, if used irresponsibly or incorrectly, can lead to irreversible consequences for
your users. This dangerous action is the capability to erase NFC tags from a mobile device.
As with all mobile capabilities, implementation of NFCService’s functionality, dangerous actions included, is at your discretion.
Use caution when using dangerous actions in your component.
NFCService Considerations
107
Use Mobile Device Features in Mobile Apps Considerations and Limitations
• NFCService is built on top of mobile operating system and device features. NFCService’s capabilities therefore depend on Android
or iOS features, which are subject to change beyond our control. When mobile operating system features change, the behavior of
NFCService can change without notice.
108
CHAPTER 4 Offline Considerations and Limitations
In this chapter ... LWC Offline is designed to let you build great apps that can function without a network connection, but
it’s not the full Salesforce service. Lightning web components have a number of limitations when used
• General offline, including missing capabilities, reduced performance, and software defects (bugs). Keep these
Considerations limitations in mind as you design and develop your offline customizations.
• Considerations for
Field Service Mobile
App
• Base Components
Support
• Modules Support
• Wire Adapters
Support
• Entity Support
• Metadata and
Custom Metadata
Types Support
109
Offline Considerations and Limitations General Considerations
General Considerations
Consider these general details when planning your Lightning web components development efforts.
• The Lightning Web Components framework includes a wide range of built-in components, a number of modules that enable features,
and a range of wire adapters for data access. The implementation available in LWC Offline supports a subset of these features. See
additional details elsewhere in this guide.
• You can only use Lightning web components that are used as global or object-specific quick actions.
• Object-specific quick actions can only be added to record detail pages.
• Your components must be Lightning web components.
– You can’t use Aura-based Lightning components, despite the similar name.
– You can’t use Visualforce at all with Lightning web components.
110
Offline Considerations and Limitations Base Components Support
• (iOS only) Changes to Lightning web components are loaded into the app only when the app is fully quit and then relaunched (a
“cold start”).
lightning-datatable This complex component was never designed for mobile use, and
its behavior in mobile contexts is subject to change without notice.
See this post in the Trailblazer community for sample code for a
simplified, mobile-friendly data table.
lightning-file-upload
lightning-formatted-address The static map feature only works in online mode. If a user is offline,
an error message is displayed instead.
lightning-formatted-rich-text URLs don’t open within a navigation view; external URLs work, but
links to records don’t. Additionally, you can’t open any URL with a
target="_blank" attribute.
lightning-formatted-url URLs don’t open within a navigation view; external URLs work, but
links to records don’t. Additionally, you can’t open any URL with a
target="_blank" attribute.
lightning-input-address The address lookup feature only works in online mode. If a user is
offline, an error message is displayed instead.
111
Offline Considerations and Limitations Base Components Support
lightning-pill URLs don’t open within a navigation view; external URLs work, but
links to records don’t.
lightning-pill-container URLs don’t open within a navigation view; external URLs work, but
links to records don’t.
112
Offline Considerations and Limitations Modules Support
lightning-tree-grid
SEE ALSO:
Component Reference
Modules Support
Lightning web component modules in the lightning namespace are described in the Component Reference in the Lightning Web
Components Developer Guide. Modules scoped with @salesforce are described in @salesforce Modules in the Lightning
Web Components Developer Guide. All modules are being reviewed for correct behavior in LWC Offline-enabled mobile apps.
The following table presents current findings.
•
— Supported. Expected to behave as documented.
•
— Limited Support. Can be used, but has known (and possibly unknown) issues.
•
— Not Supported. Doesn’t work, or shouldn’t be used.
lightning/alert
Create an alert modal within your component.
lightning/confirm
Create a confirm modal within your component.
113
Offline Considerations and Limitations Modules Support
lightning/flowSupport
Provides events to control flow navigation and
notify the flow of changes in attribute values.
lightning/navigation Available for use, but supported page reference types are limited.
Generates a URL or navigates to a page reference. See Navigation for details.
lightning/platformShowToastEvent You can import this module and fire toast events. However, toast
Displays toasts to provide feedback to a user messages aren’t handled or displayed. Use lightning/alert,
following an action, such as after a record is lightning/confirm, or lightning/prompt instead.
created.
lightning/prompt
Create a prompt modal within your component.
@salesforce/apex See Use Apex While Mobile and Offline for usage details.
Import Apex methods as functions that a
component can call either via @wire or
imperatively.
@salesforce/apexContinuation See Use Apex While Mobile and Offline for usage details.
114
Offline Considerations and Limitations Modules Support
@salesforce/client/formFactor This module “works,” but always returns Small when used in an
Import a name that refers to the form factor of LWC Offline-enabled app.
the hardware running the app.
@salesforce/contentAssetUrl
Import content asset files.
@salesforce/i18n
Import internationalization properties.
@salesforce/label
Import labels defined in your Salesforce
organization.
@salesforce/resourceUrl
Import static resources defined in your Salesforce
organization.
@salesforce/schema
Import references to Salesforce objects and fields
defined in your org.
@salesforce/user
Import the current user’s ID.
@salesforce/userPermission
Import a permission and check whether it’s
assigned to the current user.
115
Offline Considerations and Limitations Wire Adapters Support
SEE ALSO:
Component Reference
Lightning Web Components Developer Guide: @salesforce Modules
createRecord Drafts-Enabled
createRecordInputFilteredBy
EditedFields
deleteRecord Drafts-Enabled
generateRecordInputForCreate
generateRecordInputForUpdate
getFieldValue
getFieldDisplayValue
116
Offline Considerations and Limitations Wire Adapters Support
getRecords Drafts-Enabled
getRecordCreateDefaults Offline-Supported
getRecordNotifyChange
updateRecord Drafts-Enabled
getObjectInfo Offline-Supported
getObjectInfos Offline-Supported
getPicklistValues Offline-Supported
getPicklistValuesByRecordType Offline-Supported
117
Offline Considerations and Limitations Wire Adapters Support
getListInfosByName
getRelatedListRecordsBatch
getRelatedListInfo Offline-Supported
getRelatedListInfoBatch Offline-Supported
getRelatedListsInfo Offline-Supported
118
Offline Considerations and Limitations Wire Adapters Support
Note: Forward looking statement: Our goal is to provide supported alternatives to getRecordUi and getListUi. If you
limit your usage of these adapters today, you’ll have an easier time migrating later.
• In the case of getRecordUi, limit yourself to getting layout metadata details, and use the data-only adapters getRecord and
getRecords for data access.
• In the case of getListUi, use the new getListInfoByName wire adapter to get list view metadata. If you must use
getListUi to access list view records, see the following considerations.
Considerations for List Adapters
List- or collection-oriented adapters such as getListUi, getRelatedListRecords, and getRelatedListCount have
limited support for offline updates. Specifically, list logic isn’t re-evaluated for changes made while you’re offline. That is, if you create or
modify a record offline and it falls into or out of the list criteria, the record isn’t added or removed from the list until you’re back online.
The list updates only after the changes sync back to Salesforce. This limitation affects list membership, but does not affect the display of
records that are a part of a list.
Here’s an example to make this clear. Let’s say you use getRelatedListRecords as a source to display a list of records, and the
related list criteria limits list membership to accounts whose name begins with “A”. While offline, if you update one of those records to
change an account name to begin with a “B”, from “Apple” to “Banana”, that record will still display in the list, with the updated account
name “Banana”. Once you return online, the change syncs to Salesforce, and the list criteria is reevaluated. The Banana account will no
longer be a member of the related list, and the wire adapter is updated, triggering a component refresh. The list of records returned by
getRelatedListRecords won’t include the record for the Banana account, and it will disappear from the list displayed in your
component’s user interface.
Considerations for getRecordUi
getRecordUi is affected by numerous issues when used while offline.
• Invoking getRecordUi on a draft record that was created while offline returns an error.
• If you edit a record such that its layout changes—for example, by changing the record type—the results of invoking getRecordUi
on that record can be inconsistent.
• If you change a relationship field on a record, and the new relationship references a record with a different object type or record
type, the results of invoking getRecordUi on that record can be inconsistent or result in an error.
In theory, if you’re able to limit changes to records while offline to the scalar (non-relationship, non-metadata affecting) fields of that
record, then invoking getRecordUi on that record should work as documented. In practice this is challenging, and when you miss
it results in inconsistent or incorrect behavior that can be hard to troubleshoot. If you must use it, exercise extreme caution.
getRecordUi is used in the implementations of the following Lightning base components, causing them to have similar limitations:
• lightning-record-form
• lightning-record-edit-form
• lightning-record-view-form
119
Offline Considerations and Limitations Entity Support
errors = [ errors ];
}
SEE ALSO:
Lightning Web Components Developer Guide: lightning/ui*Api Wire Adapters and Functions
Entity Support
LWC Offline uses the UI-API to access entity data. The UI-API supports a long list of standard entities, and all custom entities.
For a complete list of supported entities, see Supported Objects in the User Interface API Developer Guide.
Note: The ContentDocument, ContentVersion, and associated entities, used as part of file uploading features, aren’t fully supported
at this time. This limitation affects all base components that provide file uploading functionality. See Upload Photos from LWCs
Using lightning-input Base Component in the Trailblazer community for additional details and a partial work-around.
The following entities aren’t fully supported by UI-API, but are commonly used in Field Service. Support for them is incomplete.
• Case (not supported in related lists)
• LinkedArticleTask (recurrence isn’t supported)
• WorkOrder (not supported in related lists)
• WorkOrderStatus (not supported in related lists)
• WorkOrderLineItem (not supported in related lists)
SEE ALSO:
User Interface API Developer Guide: Supported Objects
User Interface API Developer Guide
SEE ALSO:
User Interface API Developer Guide
120
CHAPTER 5 Offline Environment Details
In this chapter ... The offline environment presents a number of technical challenges for LWC Offline-enabled mobile
apps, and for your Lightning web components.
• What Happens When
Something Isn’t
The Salesforce Field Service mobile app is heavily optimized for offline use. These optimizations are
Primed (Preloaded) enabled by our complete understanding of how the built-in features are implemented, including code,
data, and metadata relationships. The app contains or loads the information it needs for built-in features
• Create Components
to perform well, online and offline. See Offline Priming in the Field Service Mobile App in Salesforce Help
with Offline Analysis
for more details.
In Mind
• Determine Online or The Field Service mobile app doesn’t, and can’t, have this same level of knowledge about your custom
Offline Status features built with Lightning web components. Instead, the app analyzes your custom objects, page
layouts, components, and other metadata, and then loads the data and metadata it thinks you need. To
improve the quality of this analysis, and thus the performance of your components, you must follow a
number of guidelines when developing your Lightning web components.
121
Offline Environment Details What Happens When Something Isn’t Primed (Preloaded)
// Don’t make the getter name the same as the import name
// This prevents priming the imported recordContextQuery
get recordContextQuery() {
return recordContextQuery(this.objectApiName);
}
}
122
Offline Environment Details Determine Online or Offline Status
Tip: See Validate Lightning Web Components for Offline Use to install validation tools that provide support within VS Code for
the previous guidelines.
During initial priming when the app loads, the “current page” can’t be known. This means that resources associated with that page —
layout metadata, object and field metadata, record data — can’t be fully determined in advance. And so the component can’t be primed
completely.
The workaround in this case, and in general, is to find another way to make these dependencies explicit, instead of implicitly defined by
a reference that can’t be resolved until runtime. Referencing a specific recordId, recordTypeId, or apiName provides enough
information to determine the dependencies without the specific page context.
123
CHAPTER 6 Use Salesforce Features While Offline
In this chapter ... Although LWC Offline is intended to “just work” when you use features while offline, there are nuances
and additional considerations for using some features while offline. This chapter provides details for how
• Use GraphQL While to use these features effectively in LWCs to make them offline-ready.
Mobile and Offline
• Use Apex While
Mobile and Offline
• Use Images in an
LWC Offline-Enabled
Component
• Upload Images While
Offline
• Use Third-Party
JavaScript in an LWC
Offline-Enabled
Component
• Navigation
124
Use Salesforce Features While Offline Use GraphQL While Mobile and Offline
Getting Started
• The fastest way to get up to speed on GraphQL and learn how to use it with the Salesforce Platform is to read the GraphQL API
Developer Guide.
• The fastest way to get up to speed on using GraphQL in Lightning web components is to read the Use the GraphQL Wire Adapter
chapter of the same developer guide. You’ll also want to refer to the lightning/uiGraphQLApi Wire Adapters and Functions
reference in the Lightning Web Components Developer Guide.
• The fastest way to learn how to build offline-ready LWCs with GraphQL is to keep reading this chapter.
If you’re new to GraphQL, you should plan to read and absorb all of these resources, in the order listed.
IN THIS SECTION:
Understand Salesforce GraphQL Implementations
Salesforce offers three different ways for LWC developers to use GraphQL in their components. Which one you select for your
components will depend on the specific needs of your application.
Feature Limitations of Offline GraphQL
Offline GraphQL uses the same wire adapter mechanism as the standard (online only) LWC wire adapter for GraphQL. You don’t
need to change any code to use Offline GraphQL, and your component can be used while online and offline.
Best Practices for Using GraphQL in LWC Offline
There are a number of best practices to be aware of when using GraphQL in your offline-ready components and apps.
125
Use Salesforce Features While Offline Feature Limitations of Offline GraphQL
The GraphQL API endpoint is accessible to any network-connected client, using any REST-capable tool, framework, or language. It’s also
the fastest way to “play” with the API; see Quick Starts: GraphQL API to quickly get started using a REST client.
GraphQL Wire Adapter for Lightning Web Components
The GraphQL Wire Adapter lets LWC developers use GraphQL via a wire adapter. Using a wire adapter simplifies the management of
your data by using Lightning Data Service (LDS).
Using GraphQL via the wire adapter simplifies making requests and handling responses, and allows your components to leverage other
features of LDS, such as caching data and requests for improved performance. The flexibility and expressiveness of GraphQL can enable
you to use GQL instead of Apex for advanced data retrieval operations. Preferring LDS and wire adapters over Apex is a best practice,
and part of the LWC Data Guidelines.
Offline GraphQL
Offline GraphQL is an implementation of GraphQL built into LWC Offline, which can run on a mobile device, even when it’s not connected
to the Internet. Offline GraphQL uses the same GraphQL wire adapter as online-only components—you don’t have to change your code
at all. Indeed, when a mobile device is online, it seamlessly uses the standard (not offline-enabled) GraphQL wire adapter.
However, when a mobile device is offline, and your LWC runs in an LWC Offline-enabled mobile app, Offline GraphQL is used, again,
automatically. Offline GraphQL runs client-side, on the mobile device, without a network connection. It uses data and metadata that is
already on the device in the Offline Cache, preloaded either by priming or by normal client activity.
Offline GraphQL has a number of limitations you need to be aware of. The standard implementations of GraphQL have access to your
org’s complete data and metadata, as well as access to the server-side resources of a vast data center. Offline GraphQL has ... your phone.
That might sound limiting, and it is. Offline GraphQL isn’t magic. There’s no sufficiently advanced GQL query that can load data that’s
not already present on the device. But with smart data access strategies you can make your custom LWCs perform work that looks like
magic to folks who need to use them in places without network access.
• For LWC developers building components that need to work offline, your only option is Offline GraphQL. (Keep reading.)
126
Use Salesforce Features While Offline Feature Limitations of Offline GraphQL
Note: This subset grows in every release. There will usually be a delay in new features, and there will always be features that can’t
be supported while disconnected from Salesforce service.
Let’s get to the largest disappointments first. There are a few major features that simply don’t work while offline:
• Aggregate queries
• Mutations (data modification)
• Pagination
Where these features are required for your component or app to function, you will need to build them yourself, or use other data access
mechanisms besides GraphQL.
• scope argument:
– MINE is supported for all entities.
– ASSIGNEDTOME is supported for ServiceAppointment.
– No other scopes are supported by Offline GraphQL.
• orderBy
– Ordering is supported, but can have a negative impact on performance. Keep in mind where the sorting is taking place (that
is, your phone). Keep your sort criteria simple, and don’t sort more records than you need to.
– Ordering results by a picklist field sorts by the picklist label, rather than the order of the picklist values defined in Setup.
127
Use Salesforce Features While Offline Best Practices for Using GraphQL in LWC Offline
Metadata
Necessary object metadata, such as custom objects, fields, layouts, and so on, is automatically loaded and cached during priming and
online activity. GraphQL lets you manually query for metadata when the occasion calls for it. When offline, there are some limitations.
• Metadata fetched through GraphQL is cached separately from metadata fetched through the getObjectInfo wire adapter.
They might not always be perfectly in sync.
• Related list metadata might work, but is unsupported at this time.
• GraphQL query performance can be suboptimal on complex queries that filter or order by non-indexed fields.
• Queries that reference offline-created (draft) records in the predicate (directly in the query, or indirectly through variables) return
locally cached results only. The query won’t make a network request to the server.
Important: Metaschema directives in GraphQL queries were deprecated in the Summer ’23 release. However, if your GraphQL
query fails prefetch in the Salesforce mobile app, Salesforce Field Service, or Mobile Offline, you must continue to use metaschema
directives in your GraphQL query for referential integrity and offline priming functionality. See Known Issue: GraphQL query fails
prefetch with an "Unknown Field" warning.
SEE ALSO:
Understand Salesforce GraphQL Implementations
128
Use Salesforce Features While Offline Use Apex While Mobile and Offline
get myQuery() {
return gql`query getSomeAccount($recordId: ID) {
uiapi { query { Account(...) { } } }`;
}
get myVariables() { return { recordId: '...' } }
In contrast, this example behaves the same as the preceding code, as long as you’re online, but does not result in the wire adapter results
being primed. If the required data and metadata isn’t primed by some other mechanism, it won’t function while you’re offline.
// ANTI-PATTERN
// This inline GQL query cannot be primed
@wire(graphql, {
query: gql`query getSomeAccount($recordId: ID) {
uiapi { query { Account(...) { } } }`,
variables: {recordId: '...'}
})
wiredData;
Important: Before you make plans to reuse existing Apex custom code in your offline features, read important details about
offline caching for Apex in Apex Results Are Separate from Other Primed Data.
IN THIS SECTION:
Use Apex in Lightning Web Components While Online
The essentials of using Apex within Lightning web components are described in "Call Apex Methods" in the Lightning Web Components
Developer Guide. While Apex features behave as documented when a client device is online, there are additional features available
within an offline-enabled mobile app.
Enable Caching of Apex Results
To allow results of Apex calls to be saved for offline use, enable caching on Apex methods used in your offline-enabled mobile apps.
129
Use Salesforce Features While Offline Use Apex in Lightning Web Components While Online
IN THIS SECTION:
Reactive Apex Wires
Reading data via a wire adapter is the “natural” way to access data in Lightning web components. To add a read-only Apex method
to a Lightning web component, first import the Apex method from the @salesforce/apex module, and then use the @wire
annotation to connect that method to a property or function in your component.
Imperative Apex
Imperative Apex is the more traditional way to call an Apex method, as a network-based API call. Imperative Apex allows you to
control exactly when the method is called. You’re in control of the invocation, rather than the framework.
130
Use Salesforce Features While Offline Enable Caching of Apex Results
These points are standard behavior for Lightning web components. They aren’t specific to the additional mobile and offline features of
an offline-enabled mobile app.
What is different is the cache. The mobile app saves the results of @wire calls to Apex methods in a durable store, instead of an
in-memory cache. The durable store is longer-lived than the standard cache used by Lightning web components. The standard cache
is designed for performance, rather than offline use. The durable store, in contrast, is designed specifically for offline use. It survives client
app restarts, and even device restarts. Data in the durable store is available to provide a result for an Apex method call, even when offline.
Again, see considerations in Apex Results Are Separate from Other Primed Data.
Imperative Apex
Imperative Apex is the more traditional way to call an Apex method, as a network-based API call. Imperative Apex allows you to control
exactly when the method is called. You’re in control of the invocation, rather than the framework.
Imperative Apex is more flexible—and less restrictive—than reactive Apex wires. For example, you can use imperative Apex calls to
change data on the server. The full details are described in Call Apex Methods Imperatively in the Lightning Web Components Developer
Guide.
However, imperative Apex has a significant limitation in an offline-enabled mobile app. You can’t use imperative Apex while offline.
This is by design, since imperative Apex is allowed to change data on the server. There’s no way to reconcile what might change on the
server side with data cached on the client side. This is because the client has no knowledge of the implementation of a server-side Apex
method. See Imperative Apex While Offline.
SEE ALSO:
Lightning Web Components Developer Guide: Client-Side Caching of Apex Method Results
131
Use Salesforce Features While Offline Apex Results Are Separate from Other Primed Data
Data that’s loaded during priming activities, or that’s loaded using base components, wire adapters, and other built-in features of
Lightning web components, is stored in one consolidated cache. In an offline-enabled mobile app, it’s also saved to the durable store
for offline use. As you load new data, it’s merged into the local store of cached data. This merging includes updating existing items with
changes loaded from Salesforce.
The mechanism that makes this possible is Lightning Data Service, or LDS. LDS results include metadata about the returned results. This
metadata, sometimes referred to as ObjectInfo, allows LDS to treat the results as real Salesforce objects.
Apex requests are different. While Apex methods can return nothing more than records, there’s nothing that ensures this. Apex requests
can return arbitrary data, in any format you build in your Apex code. As a result, Apex methods don’t return ObjectInfos for the data
contained in the response. And without the ObjectInfos for the results, there’s no way to treat those results as Salesforce records—and
therefore no way to merge them in with records saved locally by LDS.
To simplify the actual implementations, think of LDS results as being records that are indexed by record ID, with each record stored in
a separate representation of a Salesforce object. In contrast, Apex results are stored as one big opaque blob per request, indexed on the
request URL, including parameters.
While you can interpret structured data inside that opaque blob, LDS and the LWC framework can’t. If you load the same records with
LDS and Apex, those records are stored separately, as duplicates. Updates to one copy don’t affect the other, unless you fire the Apex
request again (to load changes performed via LDS), or tell the framework to reload stale LDS data (to load changes performed via Apex).
This poses a challenge for implementing features that use both the built-in data access features of Lightning Web Components and the
fully customizable logic of Apex. Our advice is to use the base Lightning components whenever possible, then use LDS wire adapters,
and then if necessary, use Apex. An extensive discussion of this tiered strategy can be found in Data Guidelines in the Lightning Web
Components Developer Guide.
Note: We recognize that LDS and built in components don’t cover every use case, and that there’s always a place for custom
logic performed on the server, especially for transactional operations. We intend to improve the capabilities of LDS over time,
including adding advanced capabilities for complex queries and other operations. We advise planning your use of Apex in such
a way that you can refactor your data access logic to adopt new LDS features as they become available.
SEE ALSO:
Lightning Web Components Developer Guide: Data Guidelines
Lightning Web Components Developer Guide: Client-Side Caching of Apex Method Results
132
Use Salesforce Features While Offline Understand Apex Behavior While Offline
IN THIS SECTION:
Apex Wires While Offline
Lightning web components that wire properties or functions to Apex methods continue to provide cached values from the durable
store, if available.
Imperative Apex While Offline
Imperative Apex calls always fail when the client device is offline. When using imperative Apex in an offline-enabled mobile
app, it’s essential to handle the possibility of a network failure error.
Refresh Records Cached in Durable Store While Offline
While it’s not possible to retrieve updated data from Salesforce while a client device is offline, it’s still possible to request updates
when data is known to be stale.
SEE ALSO:
Lightning Web Components Developer Guide: Client-Side Caching of Apex Method Results
133
Use Salesforce Features While Offline Understand Apex Behavior While Offline
handleLoad() {
getContactList()
.then(result => {
this.contacts = result;
})
.catch(error => {
this.error = error;
});
}
}
Offline-savvy components expect to be offline at times, and know what to do when that happens.
SEE ALSO:
Lightning Web Components Developer Guide: Client-Side Caching of Apex Method Results
Lightning Web Components Developer Guide: @salesforce/apex in @salesforce Modules
134
Use Salesforce Features While Offline Additional Considerations for Apex in an Offline-Enabled
Mobile App
Note: Support for offline images requires that both your Salesforce org and your mobile app are updated to the Summer ’23
release (API 58.0) or later.
IN THIS SECTION:
Use Images Uploaded as Files (ContentDocument) in an LWC
Files are a general mechanism to upload and make binary files, such as images, available in your Salesforce org. Files can be associated
with a specific record, which makes them ideal for product photos, images captured during a service call or other transaction, and
otherwise adding images to business activities that you track in Salesforce.
Use Images Uploaded as Asset Files
Asset files are the modern alternative to static resources. Asset files are ideal for images that are used throughout your components
and apps—for example, user interface elements like icons—or otherwise aren’t related to a specific record.
135
Use Salesforce Features While Offline Use Images Uploaded as Files (ContentDocument) in an LWC
Important: While there are other methods for referencing images in an LWC, the preceding elements are required for offline
image access to function. The Komaci static analyzer looks for this specific pattern when determining images to prime. Additionally,
your getter function must be statically analyzable. If its result can only be determined at runtime, the image can’t be primed.
Example: The following example is simple, and uses a hard-coded ContentDocument record ID, but it illustrates the details.
You can also access named renditions (thumbnails) of the image by adding a thumb parameter to the URL.
// imageFromContentDocument.js
import { LightningElement, wire } from 'lwc';
import { getFieldValue, getRecord } from 'lightning/uiRecordApi';
import IMAGE_URL_FIELD from
'@salesforce/schema/ContentDocument.LatestPublishedVersion.VersionDataUrl';
get imageUrl() {
return getFieldValue(this.contentDocImage.data, IMAGE_URL_FIELD);
}
get resizedImageUrl() {
return getFieldValue(this.contentDocImage.data, IMAGE_URL_FIELD) +
'?thumb=THUMB240BY180';
}
}
136
Use Salesforce Features While Offline Use Images Uploaded as Asset Files
With the image URL provided by the getter functions in the preceding component JavaScript, referencing the images in the HTML
template is just like referencing any image in HTML. Use it in the src attribute of an HTML img tag.
<!-- imageFromContentDocument.html -->
<template>
<lightning-card>Display an image from
ContentDocument {imageUrl}</lightning-card>
<template if:true={contentDocImage}>
<img src={imageUrl}/>
</template>
<template if:true={contentDocImage}>
<img src={resizedImageUrl}/>
</template>
</template>
This feature works in LWC Offline beginning in Spring ’23, which is API version 57.0. Be sure to set that minimum API version for
any component that references images while offline.
<?xml version="1.0" encoding="UTF-8"?>
<!-- imageFromContentDocument-meta.xml -->
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>57.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__RecordAction</target>
<target>lightning__GlobalAction</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordAction,lightning__GlobalAction">
<actionType>ScreenAction</actionType>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
SEE ALSO:
User Interface API Developer Guide: Upload Files
Salesforce Object Reference Guide: ContentDocument
Salesforce Object Reference Guide: ContentVersion
137
Use Salesforce Features While Offline Use Images Uploaded as Asset Files
Referencing an image stored in an Asset file is straightforward, and fully documented. We present only a simple example here. See Access
Content Asset Files the Lightning Web Component Developer Guide for complete details.
The critical elements of an offline-ready implementation are:
• Access the URL of the asset using the @salesforce/contentAssetUrl module.
• Provide the image URL via a getter function.
• Use the getter function for the src attribute of an img tag in your HTML template.
Important: While there are other methods for referencing images in an LWC, the preceding elements are required for offline
image access to function. The Komaci static analyzer looks for this specific pattern when determining images to prime. Additionally,
your getter function must be statically analyzable. If its result can only be determined at runtime, the image can’t be primed.
Example:
// imageFromAssetFile.js
import { LightningElement } from 'lwc';
import ASSET_IMG from '@salesforce/contentAssetUrl/avatars-light-mode';
import ARCHIVE_IMG from '@salesforce/contentAssetUrl/branding-images';
get assetArchiveUrl() {
return ARCHIVE_IMG + '&pathinarchive=images/logo-large.png';
}
}
Warning: The assetArchiveUrl function in the preceding example appends a pathinarchive query parameter
and value, using a “&” separator. The “&” isn’t used in examples in the standard LWC documentation. The need for the “&”
separator is inconsistent between desktop and mobile today, and we consider this discrepancy to be a software defect. For
now, adding the “&” separator generally works on both desktop and mobile, even though it results in a double “&&” on
desktop.
With the image URL provided by the getter functions in the preceding component JavaScript, referencing the images in the HTML
template is just like referencing any image in HTML. Use it in the src attribute of an HTML img tag.
<!-- imageFromAssetFile.html -->
<template>
<lightning-card>
Display an image directly from an Asset file {assetUrl}
</lightning-card>
<template if:true={assetUrl}>
<img src={assetUrl}/>
</template>
<lightning-card>
Display an image from an archive Asset file {archUrl}
</lightning-card>
<template if:true={assetArchiveUrl}>
<img src={assetArchiveUrl}/>
138
Use Salesforce Features While Offline Use Images Uploaded as Static Resources
</template>
</template>
SEE ALSO:
Salesforce Help: Asset Files
Lightning Web Components Developer Guide: Access Content Asset Files
Lightning Web Components Developer Guide: @salesforce/contentAssetUrlin @salesforce Modules
Important: While there are other methods for referencing images in an LWC, the preceding elements are required for offline
image access to function. The Komaci static analyzer looks for this specific pattern when determining images to prime. Additionally,
your getter function must be statically analyzable. If its result can only be determined at runtime, the image can’t be primed.
Example:
// imageFromStaticResource.js
import { LightningElement } from 'lwc';
import TRAILHEAD_LOGO from '@salesforce/resourceUrl/trailhead_logo';
Warning: LWC Offline doesn’t support archive static resources at this time. While you can upload each image as a separate
static resource, we recommend that you use Content Assets, which do support archive files, for collections of related images.
See Use Images Uploaded as Asset Files.
With the image URL provided by the getter function in the preceding component JavaScript, referencing the image in the HTML
template is just like referencing any image in HTML. Use it in the src attribute of an HTML img tag.
<!-- imageFromStaticResource.html -->
<template>
<lightning-card>
Display an image directly from a static resource: {trailheadLogoUrl}
</lightning-card>
139
Use Salesforce Features While Offline Image Priming and Offline Considerations
<template if:true={trailheadLogoUrl}>
<img src={trailheadLogoUrl}/>
</template>
</template>
SEE ALSO:
Salesforce Help: Static Resources
Lightning Web Components Developer Guide: Access Static Resources
Lightning Web Components Developer Guide: @salesforce/resourceUrlin @salesforce Modules
Note: Only the img tag is supported at this time. Images referenced in other ways or tags aren’t primed and won’t display
sometimes, even when online.
Primed images are stored locally on the mobile device, in a binary durable store (cache). Images stored in individual files are primed and
cached individually. Images stored in archive asset files are accessible, but be aware that the entire archive is primed and cached. Updates
to images in archive files require reloading the entire archive. Archive static resources aren’t supported at this time.
In Summer ’23, primed images aren’t automatically purged from the offline cache when they get stale. Be mindful of the size of your
images or archive asset files, and the space they take up locally on devices. LWC Offline-enabled apps can provide other methods of
purging stale images. Check the documentation for your target mobile app.
The binary contents of an item referenced in an img tag isn’t validated. It’s up to you to ensure that referenced files are valid images.
Support for specific image formats is dependent on the capabilities of the web view, which is provided by the operating system. Providing
an unsupported or non-image file to an img tag is an HTML error and can cause unpredictable behavior. As the joke goes, don’t do
that. Safe formats are the usual web image formats: GIF, JPEG, PNG, and so on. When in doubt, test specific image formats on your specific
supported mobile devices and operating system versions.
Important: This feature is available only in Salesforce mobile apps, such as Salesforce Mobile App Plus and Field Service Mobile.
This feature depends on functionality built into these mobile apps. While LWCs that use this feature don’t emit errors when used
on desktop, they don’t function as intended, either.
Your organization must purchase and license Salesforce Mobile App Plus in order to use this feature in the Salesforce mobile app.
Contact your Salesforce sales rep for more information.
140
Use Salesforce Features While Offline Understand File Uploads in Salesforce
IN THIS SECTION:
Understand File Uploads in Salesforce
It’s simple to upload files and attach them to other records in the Salesforce user interface, but a great deal takes place behind the
scenes. File uploads have a complex representation in Salesforce. This complexity makes it challenging to work with file uploads
programmatically in LWC code, especially in a way that works while a mobile device is offline.
Image Upload Basics
Uploading an image from an LWC using features supported offline is a two-step process. First, use
createContentDocumentAndVersion to upload the image file. This adapter creates ContentDocument and
ContentVersion records for the file upload. After the ContentDocument and ContentVersion exist, use
createRecord to create the ContentDocumentLink record that relates the image upload to the record you want to
attach it to.
Image Upload Example
Here’s a quick example of uploading an image to Salesforce using the createContentDocumentAndVersion adapter.
This technique works on mobile devices, whether they’re online or offline. This technique works only in Salesforce mobile apps.
Warning: This diagram oversimplifies file uploads in Salesforce. It omits ownership, sharing, and other features supported by
additional objects and APIs. For more details, including available fields and usage notes, start with ContentDocument, ContentVersion,
and ContentDocumentLink in the Salesforce Object Reference.
An uploaded, attached, or generated file is represented primarily by the ContentDocument object. However, this object holds no
file data. Instead, versions of an uploaded file are stored as ContentVersion objects. With this structure, you can update a file by
uploading a new version. Each upload creates another ContentVersion record, and this record is where the binary file data for
the upload is stored.
That record represents the file. To associate an uploaded file to another record—for example, to attach photos of a vehicle to a car rental
agreement record—the ContentDocumentLink object is used to link the two records together. A ContentDocumentLink
object represents the relationship between a ContentDocument and any other record. Associate an uploaded file with any number
of other records by creating the appropriate ContentDocumentLink records that join them.
When online, the LWC code for creating a file upload, while non-trivial, is straightforward, using standard Lightning Data Service (LDS)
adapters like createRecord.
141
Use Salesforce Features While Offline Image Upload Basics
Supporting offline uploads from mobile clients is more challenging. Not only is it hard to manage the various relationships between
records, but there’s also the challenge of holding binary file data in an offline store for later upload. To manage these technical issues,
use the dedicated, mobile-specific file upload adapter: createContentDocumentAndVersion.
142
Use Salesforce Features While Offline Image Upload Example
<lightning-input
type="text"
label="Description"
value={descriptionValue}
onchange={handleDescriptionInputChange}
></lightning-input>
</div>
143
Use Salesforce Features While Offline Image Upload Example
@track
files = undefined;
@track
uploadingFile = false;
@track
titleValue = "";
@track
descriptionValue = "";
@track
errorMessage = "";
// Getter used for local-only processing. Not needed for offline caching.
// eslint-disable-next-line
@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement
get fileName() {
// eslint-disable-next-line
@salesforce/lwc-graph-analyzer/no-unsupported-member-variable-in-member-expression
const file = this.files && this.files[0];
if (file) {
return file.name;
}
return undefined;
}
// Input handlers
handleFilesInputChange(event) {
this.files = event.detail.files;
this.titleValue = this.fileName;
}
handleTitleInputChange(event) {
this.titleValue = event.detail.value;
}
handleDescriptionInputChange(event) {
this.descriptionValue = event.detail.value;
}
144
Use Salesforce Features While Offline Image Upload Example
this.titleValue = "";
this.descriptionValue = "";
this.errorMessage = "";
}
try {
this.uploadingFile = true;
145
Use Salesforce Features While Offline Image Upload Example
notifySuccess() {
this.dispatchEvent(
new ShowToastEvent({
title: "Upload Successful",
message: "File enqueued for upload.",
variant: "success",
})
);
}
}
For the purpose of explanation, we can divide the implementation into these four sections.
• Import statements
• State tracking
• Simple convenience functions and change handlers
• The file upload handler
Import Statements
The only thing interesting about the import statements is the API function, createContentDocumentAndVersion. The file
upload discussion describes how to use this function.
State Tracking
This component’s state tracking consists of one @api public attribute and five @track internal state attributes.
• recordId is public and allows the component to receive a record context. This context is used to associate (attach) files that are
uploaded to the record from which the component is launched. For example, to attach photos of equipment installed to the Service
Appointment record of a technician’s visit.
• files holds the currently selected local file prior to being uploaded. This variable is used to hold a file locally while the Title and
Description are edited. It’s an array so that, with some minor code changes, you can upload multiple files at a time.
• titleValue and descriptionValue hold the form field values for editing via the form fields.
• uploadingFile indicates active processing and is used to manage the Upload button’s enabled or disabled state.
• errorMessage holds messages about any errors that occur when the actual upload is attempted.
146
Use Salesforce Features While Offline Image Upload Example
This one call creates two related records. One record is a ContentDocument representing the file, including the name and description.
The second is a related ContentVersion record that holds the file data and represents the current version of the uploaded file.
This one call does a lot of work, including creating the relationship between the two records. While you can achieve the same end result
using the createRecord adapter, you can do that only while online. Creating and preserving the relationship between the two
isn’t possible using createRecord while offline, mostly due to the complexity of the representation of files in Salesforce.
createContentDocumentAndVersion abstracts that complexity, making file uploads as simple as the preceding snippet,
which is just one line of code, wrapped for readability.
createContentDocumentAndVersion creates a file upload, but it does not associate that uploaded file with the “owning”
record for the record context (if any). After it completes the upload (notice the await keyword before the call), we verify that we have
a record context (recordId). If so, call the createContentDocumentLink helper function to create that association, in the
form of a ContentDocumentLink record.
147
Use Salesforce Features While Offline Use Third-Party JavaScript in an LWC Offline-Enabled
Component
If handleUploadClick is exotic for using a mobile only API function, createContentDocumentLink is boring, using
createRecord, a staple of LWC code since the framework’s release.
This code is another one-liner when you unwrap it. The trick is knowing enough about the representation of files and their relationship
to other object types in Salesforce. In this case, it’s knowing that ContentDocumentLink represents a relationship between an
uploaded file and another record, and knowing which fields to stick the relevant record IDs into.
Tip: ShareType: "V" might seem a bit mysterious, but it’s simple and not particularly relevant. It sets the sharing level to
view-only. See ContentDocumentLink in the Object Reference for the Salesforce Platform for details.
Important: LWC Offline doesn’t support archive static resources at this time. This limitation poses a challenge for libraries that
consist of many separate JavaScript files. While you can create a separate static resource for each file and load them individually,
that’s tedious. Look for a merged, concatenated, or minimized version of your JavaScript library; transformed versions of libraries
are often provided by the developer for performance and ease of deployment.
The critical elements of an offline-ready implementation are:
• Access the URL of the resource by importing it using the @salesforce/resourceUrl module.
• Load the library using the loadScript() function of the platformResourceLoader module, and then;
• Call your library’s entry point, initialization or factory function, or otherwise start using the library in a then() block chained from
your loadScript() call.
Important: While there are other methods for loading JavaScript libraries in an LWC, the preceding elements are required for
offline access to function. Static resources aren’t primed in advance; users must load (view) a component using the static resource
before going offline. This behavior will change in a future release.
148
Use Salesforce Features While Offline Navigation
Example:
// javascriptFromStaticResource.js
import { LightningElement } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import myLib from '@salesforce/resourceUrl/myLib';
If you must load multiple separate JavaScript files, wrap them in a Promise, and call the initialization function after all of your calls
to loadScript() have resolved. For example:
Promise.all([
loadScript(this, resourceName1),
loadScript(this, resourceName2),
loadScript(this, resourceName3)
]).then(() => {
// Start using the library here
});
SEE ALSO:
Salesforce Help: Static Resources
Lightning Web Components Developer Guide: Use Third-Party JavaScript Libraries
Lightning Web Components Developer Guide: @salesforce/resourceUrlin @salesforce Modules
Lightning Web Components Developer Guide: Platform Resource Loader
Navigation
Build navigation for Lightning web components.
When we talk about “navigation,” we can broadly separate things into two categories: things that appear on the screen—buttons, tabs,
links, and so on—and what actually happens when someone interacts with those things. Call these two categories navigation user
experience and navigation actions. These terms are loose, not specific to Salesforce, mobile apps, or Lightning web components, and we
use them informally here.
IN THIS SECTION:
Navigation User Experience
There are a variety of base components available to design the visual user interface that users tap or click to move around in your
app.
Base Components with Built-In Navigation Actions
Use base components that have automatic or built-in navigation actions.
149
Use Salesforce Features While Offline Navigation User Experience
lightning-carousel-image Behaves like a hyperlink if a URL is provided via the href attribute.
lightning-click-to-dial Displays a formatted phone number as click-to-dial enabled or disabled for Open
CTI and Voice.
lightning-formatted-address Displays a formatted address with a link to the given location on Google Maps.
lightning-formatted-phone Displays a phone number as a hyperlink with the tel: URL scheme.
lightning-formatted-rich-text Creates hyperlinks in rich text automatically for linkable text and email addresses.
lightning-formatted-text URLs and email addresses are displayed as hyperlinks when you specify the
linkify attribute.
lightning-pill Behaves like a hyperlink if a URL is provided via the href attribute.
lightning-vertical-navigation Behaves like a hyperlink if a URL is provided via the href attribute.
Note: Some of these components have limitations when used in an offline-enabled mobile app. See Base Components Support
for details.
There are additional base components that can have navigation actions attached to them, such as buttons and tabs. These components
require you to add click handlers or other functionality in the form of JavaScript code. See Programmatic Navigation Actions.
150
Use Salesforce Features While Offline Programmatic Navigation Actions
There’s a wide range of targets available for deep linking into the Field Service mobile app. See Deep Linking Schema for the Field Service
Mobile App in the Field Service Developer Guide for available URL formats.
This action can also be used as a deep link into the Field Service mobile app. See Deep Linking Schema for the Field Service Mobile App
in the Field Service Developer Guide for additional details.
151
Use Salesforce Features While Offline Programmatic Navigation Actions
}
}
See Configure Deep Linking for the Salesforce Mobile App for available URL formats.
152
CHAPTER 7 Development Tools and Processes
In this chapter ... Set up and use your development tools for the most efficient developer experience while building mobile
and offline LWCs.
• Understand the
Mobile Development
Developing LWCs and apps for use in Salesforce mobile apps uses all the same developer tools and
Cycle processes that developing LWCs for desktop use. It also poses special challenges, especially in the areas
of testing and debugging. This chapter describes a number of additional tools and processes designed
• Set Up Your
specifically for developing mobile LWCs.
Development
Environment
• Preview Lightning
Web Components on
Mobile
• Validate Lightning
Web Components for
Offline Use
• Develop
Offline-Ready LWCs
with the LWC Offline
Test Harness
• Debug Your
Components with
Virtual Device Builds
• Customize the Offline
Experience for the
Salesforce Mobile
App
153
Development Tools and Processes Understand the Mobile Development Cycle
Code
You know what this part is. Actually writing code in your development editor of choice. Coding is the fun part of every developer’s job,
and the more time you can spend doing it, the happier you are (usually). For LWC developers working on mobile apps, the editor of
choice is VS Code. Salesforce provides multiple extensions for VS Code to make your mobile dev work easier, including Salesforce DX
extensions, mobile extensions, and code validation.
• Visual Studio Code
• Salesforce DX
• Salesforce Extensions for VS Code
• Salesforce Mobile Extensions
• Code Validation
154
Development Tools and Processes Set Up Your Development Environment
Preview
Get the current version of your code into a container that can run it. Previews need to be a fast, lightweight process, not a release
ceremony. Salesforce mobile extensions for VS Code make this happen, whether you want to preview your components in development
in a local preview environment, in the Test Harness app, or in an official Salesforce mobile app on a virtual or physical device.
• Preview Lightning Web Components on Mobile
• Salesforce Extensions for VS Code
• Salesforce Mobile Extensions
• Test Harness App
Test
Testing is an overloaded term in software development. There are many different kinds of testing. For your daily, interactive development
work, the focus is on manually testing the behavior of the code you just added or changed. Once your component is in a preview
environment, being able to tap on the app, navigate the user interface, and interactively play with your component or app is
straightforward.
• Test Harness App
• Virtual Device Builds
• Salesforce Mobile App Betas
Debug
“Where did it all go wrong?” is a question every developer asks, usually many times a day. Debugging is how you answer that question.
“Why doesn’t X happen when I do Y?” and “What does happen when I do Y?” are questions you need real debugging tools to help answer.
LWC developers depend on standard debugging tools like Chrome DevTools and Safari Web Inspector to look inside their components
to understand behavior. Mobile developers can use these same tools but, because LWC Offline code runs inside a mobile app instead
of a web browser, it’s a bit trickier to attach a JavaScript console to the web view. The mobile Test Harness app gives you not only a
debuggable web view, but also a collection of specialized tools and functions to inspect the underlying behavior of your component
code while running offline.
• Debug Lightning Web Components
• Virtual Device Builds
• Test Harness App
• Chrome DevTools
• Safari Web Inspector
155
Development Tools and Processes Set Up Your Development Environment
Note: Don’t let Android Studio or Xcode intimidate you. You only need to use it to provision a device emulator (Android) or
simulator (iOS). You don’t need both Android Studio and Xcode. If you want both, great. If not, pick the one you’re most comfortable
with.
Installation Instructions
We recommend the following installation sequence. Each link provides complete details for installing and configuring each of the
different tools.
• Install and configure Android Studio
• Install and configure Xcode
• Install the Salesforce CLI
• Install the Mobile Extensions
• Install VS Code
• Install Salesforce Extensions for VS Code
• Download the latest virtual device build for the mobile app
– For the Salesforce mobile app, use the standard virtual device builds, as described in Preview Components in the Salesforce
Mobile App.
Note: Your org must be enabled for LWC Offline before you can see or use LWC Offline features.
– For the Field Service mobile app, the download link is posted in the Trailblazer Community.
• Install a virtual device build into a configured Android emulator or iOS simulator instance
The Develop a Lightning Web Component Quick Action quick start provides hands-on instructions for setting up your development
environment, and also for creating, deploying, and running your first LWC.
IN THIS SECTION:
Set Up Xcode
Before you run previews in iOS simulators, make sure that Xcode 11 is properly installed and configured. After you install Xcode, test
your environment with the Mobile Preview setup command. If you’re using an existing Xcode installation, run the setup
command to verify that your installed environment meets Mobile Extensions requirements.
Set Up Android Studio
Before you run previews in Android emulators, make sure that Android Studio is properly installed and configured. After you install
Android Studio, test your environment with the setup command. If you’re using an existing Android Studio installation, run
setup to verify that your installed environment meets Mobile Extensions requirements.
156
Development Tools and Processes Set Up Xcode
Set Up Xcode
Before you run previews in iOS simulators, make sure that Xcode 11 is properly installed and configured. After you install Xcode, test
your environment with the Mobile Preview setup command. If you’re using an existing Xcode installation, run the setup command
to verify that your installed environment meets Mobile Extensions requirements.
Install Xcode
How you install Xcode depends on your version of macOS. Mobile Extensions supports macOS version 10.14.4 (Mojave) and higher.
If you’ve already installed Xcode, skip to “Verify Your iOS Setup.”
macOS Catalina, version 10.15.x
•
If you’re new to Xcode or are running Xcode 10 or earlier, install the latest version of Xcode from the Mac App Store . The
latest version of Xcode meets the requirements of Mobile Extensions.
macOS Mojave, version 10.14.4 minimum
• Download and install Xcode 11.3.x from developer.apple.com/downloads/more. This site requires you to log in with your Apple
ID.
If setup reports any issues, use the following steps to correct them.
1. Use a Mac: Mobile Extensions for iOS requires a Mac running macOS Mojave version 10.14.4 and higher.
a. On your Mac, click About This Mac in the System menu.
b. Under Overview, look for the operating system name and version. Examples: “macOS Catalina Version 10.15.5”, “macOS Mojave
Version 10.14.4”.
b. If none of your installed simulators use iOS 13, check and install at least one iOS 13 simulator.
157
Development Tools and Processes Set Up Android Studio
5. To see the list of installed virtual devices that Mobile Extensions recognizes on your machine, use the device:list command:
sf force:lightning:local:device:list -p ios
158
Development Tools and Processes Set Up Android Studio
1. In the Android Studio Welcome screen, click Configure > SDK Manager.
2. If you require previewing with additional API levels, download one or more SDK Platforms from API level 23 or later. For each
required level:
a. Check the box next to its name.
b.
On the same row, click Download .
Downloading new API versions can take several minutes.
c. If prompted, confirm each download, then accept the license agreement and click Next.
159
Development Tools and Processes Set Up Android Studio
Although the latest version is recommended, any version of the command-line tools is expected to work.
Note: In a new Android Studio installation, none of the images are downloaded.
160
Development Tools and Processes Set Up Android Studio
6. Click Download.
7. After the download completes and you return to the System Image list, select the downloaded image and click Next.
8. In Verify Configuration, you can change the AVD name to any value that helps you identify the configuration. For other settings, you
can accept the default values.
9. Click Finish to return to Your Virtual Devices.
10. To launch the emulator, click the Play button in your emulator’s listing.
If setup reports any issues, use the following guidelines to correct them.
System Variables
The ANDROID_HOME variable is the starting point for all Android development operations. If this variable isn’t set or is incorrect,
Mobile Extensions can’t use Android tools. You set ANDROID_HOME to point to the top-level directory of your Android SDK
installation. On macOS, for example, this variable’s default value is /Users/<user_name>/Library/Android/sdk. If
you’ve installed Android SDK in a custom directory, make sure that this path points to that location.
macOS X:
161
Development Tools and Processes Set Up Android Studio
You can make these settings persistent by adding them to the ~/.bash_profile or similar startup file for your command
shell.
• Configure ANDROID_HOME as follows.
export ANDROID_HOME=/Users/<your_user_name>/Library/Android/sdk
• For Android, the Mobile Extensions plug-in requires the Java Development Kit (JDK) version used by Android Studio. Currently,
this version is JDK 8. Your plug-in commands might fail if:
– A JAVA_HOME system variable exists on your machine and points to a different JDK version.
– Other applications in your system path use a different JDK version.
You can find the correct JDK version installed with Android Studio’s Java runtime engine embedded in the Android Studio app.
For example:
export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home"
• – Variable: JAVA_HOME
– Value: C:\Program Files\Android\Android Studio\jre
Note: For Android, the Mobile Extensions plug-in requires the Java Development Kit (JDK) version used by Android
Studio. Currently, this version is JDK 8. If you set JAVA_HOME to a custom path that points to a different JDK version,
the plug-in commands might fail.
• – Variable: JAVA_HOME
– Value: /snap/android-studio/current/android-studio/jre
Note: For Android, the Mobile Extensions plug-in requires the Java Development Kit (JDK) version used by Android
Studio. Currently, this version is JDK 8. If you set JAVA_HOME to a custom path that points to a different JDK version,
the plug-in commands might fail.
162
Development Tools and Processes Install Mobile Extensions
Check these versions in the SDK Tools section of the Android SDK Manager.
Note: In addition to the version ranges listed here, later stable versions of these tools are also expected to work.
A message that the plug-in isn’t digitally signed is expected and isn’t a cause for concern.
3. If you’re prompted to continue installation, enter y.
4. To see the available commands, use grep with sf commands, which lists the commands with a space separator rather than a
colon. Salesforce CLI commands accept either separator. For example, the setup command is in the force lightning
local topic, while the preview command is in the force lightning lwc topic:
force lightning local device list List the available virtual mobile devices
for Lightning Web Component development.
163
Development Tools and Processes Install Mobile Extensions
force lightning lwc test create creates a Lightning web component test
file with boilerplate code inside a __tests__ directory.
force lightning lwc test run invokes Lightning Web Components Jest unit
tests.
force lightning lwc test setup install Jest unit testing tools for
Lightning Web Components.
force lightning lwc test ui mobile configure Create a configuration file for running
UTAM tests on mobile.
force lightning lwc test ui mobile run Run UTAM test by specifying a WDIO
configuration. Test specs to run can be explicitly specified by using a flag.
To see the syntax of the available commands, call each command with the --help argument. For example:
sf force:lightning:local:setup --help
sf force:lightning:lwc:preview --help
• -p, --platform: Mobile platform to verify. Can be either Android or iOS (case insensitive).
• Two other parameters—--json and --loglevel—are standard Salesforce CLI conventions and aren’t part of the setup
functionality.
1. Check your Android setup status.
sf force:lightning:local:setup -p android
a. If your setup is correct, this command prints “Passed” status for all tests. You’re ready to start previewing components on Android!
b. If any test fails, follow the suggestions printed in the console to finish setting up your Android environment. To review setup
instructions, see Set Up Android Studio on page 158.
c. Repeat this step until all tests report “Passed”.
164
Development Tools and Processes Install Mobile Extensions
a. If your setup is correct, this command prints “Passed” status for all tests. You’re ready to start previewing components on iOS!
b. If any test fails, follow the suggestions printed in the console to finish setting up your iOS environment. To review setup instructions,
see Set Up Xcode on page 157.
c. Repeat this step until all tests report “Passed”.
• -p, --platform: Mobile platform to verify. Can be either Android or iOS (case insensitive).
Note:
• The preview command allows you to select any of your installed simulators. However, Salesforce can’t guarantee preview
performance on all virtual devices.
• For iOS, the list produced by this command uses the format “device name, iOS_runtime version”.
• For Android, the list produced by this command uses the format “device name, device type, Android runtime version”.
• For Android, if your development environment variables aren’t properly configured, this command returns an empty list.
• -n, --devicename
Name for the new virtual device. If the specified name is already in use on your machine, the command fails with an explanatory
error. To see the list of your existing device names, use the force:lightning:local:device:list command.
-d, --devicetype
Type of virtual device.
If the command doesn’t recognize your device type entry, choose one from the list provided by the resulting error message. For
example:
– Android:
FAILED: Validating specified device type. (0.001 sec)
› Device type 'pixel_xlst' is invalid. Must be one of the following
valid types: pixel, pixel_xl, pixel_c
– iOS:
FAILED: Validating specified device type. (0.287 sec)
› Device type '“iPhone 12 Pro Max 14.4”' is invalid. Must be one of the following
165
Development Tools and Processes Install Mobile Extensions
-p, --platform
Mobile platform to create. Can be Android or iOS (case insensitive).
-l, --apilevel
(Optional, Android only) Android API level for the new device. Default value is your latest installed API level. Not used for iOS
devices.
• Two other parameters—--json and --loglevel—are standard Salesforce CLI conventions and aren’t part of the setup
functionality.
iOS Example
sf force:lightning:local:device:create -p ios -n 'iOS test' -d 'iPhone 12 Pro Max'
Android Example
sf force:lightning:local:device:create -p android -n 'API 29 pixelXL' -d 'pixel_xl'
-l 29
This command starts by running the force:lightning:local:setup command. If that command reports failures, address
the first reported failure, and then retry the force:create command.
If you specify a device name that already exists on your machine, the command exits with the message “A virtual device with the name
'<existing_name>' already exists.”
• -p, --platform
Mobile platform of the target device. Can be Android or iOS (case insensitive).
-t, --target
Name of the virtual device to launch.
-w, --writablesystem
(Optional, Android only) Doesn’t accept a value. If present, the virtual device launches with a writable system. Otherwise, the
system is read-only.
• Two other parameters—--json and --loglevel—are standard Salesforce CLI conventions and aren’t part of the setup
functionality.
iOS Example
sf force:lightning:local:device:start -p ios -t "iPhone 12 Pro Max"
Android Examples
sf force:lightning:local:device:start -p android -t "API 29 pixelXL"
sf force:lightning:local:device:start -p android -t "API 29 pixelXL" -w
166
Development Tools and Processes Preview Lightning Web Components on Mobile
IN THIS SECTION:
Mobile Development Preview Environments
While coding components, developers can launch mobile previews from VS Code or from the command line. Developers can also
preview components in context in the Salesforce mobile app, or in a virtual device build of the Salesforce mobile app. Salesforce
admins can preview Lightning Experience on mobile from Lightning App Builder.
Preview Components from the Command Line
After you’ve installed the Mobile Extensions plug-in and set up Xcode and Android Studio, you can launch previews directly from
the command line. As you code, mobile previews immediately reflect your changes.
Preview Components from Visual Studio Code
After you’ve installed the Mobile Extensions plug-in and set up Xcode and Android Studio, install Salesforce Extensions for Visual
Studio Code. Now you can launch mobile previews from the VS Code command palette. Mobile previews immediately reflect visual
changes you make to your component as you edit.
Preview Components in the Salesforce Mobile App
To verify your Lightning web components in Salesforce on many devices, use virtual device builds of the Salesforce mobile app.
These builds make it possible to run Salesforce on iOS simulators and Android emulators.
Preview Components in Custom Mobile Apps
If you develop your own custom native apps for iOS and Android, you can adapt them to preview Lightning web components. You
provide configuration for installing your app on mobile devices and implement some means of hosting the preview. At runtime,
you use the advanced features of the lwc:preview command to send previews to your app.
Administrators
Salesforce Administrators work with stakeholders to define requirements and to customize their org, using the full variety of tools available
in Salesforce. When customizing pages, administrators should validate their changes for both desktop and mobile.
App Builder Mobile Previews
Admins can use Lightning App Builder to build apps and pages to customize Lightning Experience on mobile. App builder provides
previews for both desktop and mobile. Admins can specify certain components as mobile- or desktop-only.
For more information, see Build a Mobile App Page and the Get Ready for Lightning — 5 step-by-step videos.
167
Development Tools and Processes Mobile Development Preview Environments
If admins need more than a preview, they can run Lightning applications and components in the Salesforce mobile app on their devices.
Testing in the mobile app helps validate that users have the best experience on mobile.
Developers
Salesforce developers building Lightning web components have many options available to validate their components for mobile.
Preview with Local Development
During development you can view mobile previews for Lightning web components locally with the Salesforce Extensions for Visual
Studio Code. You can launch a mobile preview from the Command Palette while you’re editing a component. Mobile previews immediately
reflect visual changes you make to your component as you edit, before publishing to Salesforce. Local previews can display your
component in a web browser on your desktop and on a simulated mobile device.
168
Development Tools and Processes Mobile Development Preview Environments
169
Development Tools and Processes Mobile Development Preview Environments
170
Development Tools and Processes Preview Components from the Command Line
Basic Parameters
• -n, --componentname:
Name of your component.
• -p, --platform:
Mobile platform to use for the preview. Can be either Android or iOS (not case sensitive).
Advanced Parameters
• (Optional) -a, --targetapp
Target app for the preview. Acceptable values are browser, which means the default mobile browser, or an app ID. Defaults
to browser.
• (Optional) --confighelp
Displays the schema of the extended configuration file.
Here’s a macOS example of a basic call. The name of your component is helloWorld, and you’re developing it in the
~/Projects/helloWorld/ directory.
1. In a Terminal window, cd to the directory of your Lightning Web Components project.
cd ~/Projects/helloWorld/
171
Development Tools and Processes Preview Components from the Command Line
Because the server is a synchronous process, this window doesn’t accept further command input until the server is stopped.
3. Leaving the server running, open a second Terminal window or Windows command prompt in your project directory, and enter
this command:
sf force:lightning:lwc:preview -p Android -n HelloWorld -t "Pixel XL API 29"
Launching the virtual device can take a few seconds. After it has booted, the Mobile Extensions plug-in presents your component in the
device’s default browser. You can inspect and interact with your component. If you change visual aspects of your component’s code,
the simulator immediately reflects those changes without requiring a manual refresh.
Managing Devices
To manage devices:
• iOS: Use the Devices and Simulators tool in Xcode.
• Android: Use the Android Virtual Device (AVD) Manager.
To see the list of supported virtual devices in your environment, use the device:list command:
• iOS:
sf force:lightning:local:device:list ios
• Android:
sf force:lightning:local:device:list android
Use this command only after your development environment is fully configured and operational. Virtual device images are required to
match or exceed system requirements for Mobile Extensions. In addition, the following scopes can limit the number of devices shown
in the list.
iOS:
Devices must run iOS or iPadOS.
Android:
No known limitations.
Here are a few tips on how the device list works.
• If you enter a name that doesn’t match an existing virtual device, Mobile Extensions creates a device with that name.
• Android virtual devices created by Mobile Extensions are based on the latest SDK level and use Google APIs.
172
Development Tools and Processes Preview Components from the Command Line
Android
The app’s ID in the format supported by the Android Debug Bridge (adb) shell. For example, here’s the format that the adb
start command accepts:
name
The app’s “friendly” name. Salesforce VS Code Extensions use this name to identify the app.
get_app_bundle (Optional)
Name of a Node.js or TypeScript module that provides configuration for installing the app on the target device or emulator.
This module must expose a run() method that returns the path to the app bundle as a String. If this path is relative rather
than absolute, Mobile Extensions calculates the path relative to the configuration file. This module is also responsible for providing
any implementation details that allow access to the app bundle.
If the get_app_bundle argument is present, Mobile Extensions calls the run command before launching the preview. If
omitted, Mobile Extensions assumes that the bundle is already installed on the target device or emulator.
activity (Android only)
The class name of the app’s main activity in a format that supports launching the app from the Android Debug Bridge (adb) shell.
For example, here’s the format that the adb start command accepts:
In your configuration file, you use .ActivityName (including the leading period.)
launch_arguments (Optional)
An array of objects specifying arguments required for launching the app. Each object contains one argument’s name and value.
Each argument name and argument value is expressed as a name-value pair.
preview_server_enabled (Optional)
Indicates whether the native app requires a local development server for previewing a component. If false (default value), the preview
command proceeds without checking for a running server instance. If true, before beginning the preview the command checks for
a running server instance. If this check fails, the command returns an error and prompts the user to start the server before rerunning
the command.
Properties other than launch_arguments are simple name-value string pairs. Here’s a sample configuration file.
{
"apps": {
"ios": [
{
"id": "com.salesforce.mobiletooling.lwctestapp",
"name": "LWC Test App",
"get_app_bundle": "configure_ios_test_app.ts",
"launch_arguments": [
{ "name": "ShowDebugInfoToggleButton", "value": "true" },
{ "name": "username", "value": "Astro" }
],
"preview_server_enabled": true
}
],
"android": [
{
"id": "com.salesforce.mobiletooling.lwctestapp",
"name": "LWC Test App",
173
Development Tools and Processes Preview Components from Visual Studio Code
"get_app_bundle": "configure_android_test_app.ts",
"activity": ".MainActivity",
"launch_arguments": [
{ "name": "ShowDebugInfoToggleButton", "value": "true" },
{ "name": "username", "value": "Astro" }
],
"preview_server_enabled": true
}
]
}
}
You can access the schema for this file at /src/cli/commands/force/lightning/lwc/previewConfigurationSchema.json in the
forcedotcom/lwc-dev-mobile GitHub repo.
SEE ALSO:
Preview Components in Custom Mobile Apps
174
Development Tools and Processes Preview Components in the Salesforce Mobile App
7. For previews in custom native apps only: Select whether to preview the component on your mobile browser or in a custom native
app. Custom apps appear in the list when your Lightning web component project has mentioned them in its configuration file. For
VS Code, this file is required to be in the root directory of your project.
SEE ALSO:
Run Local Development SFDX Commands in VS Code
Tip: Salesforce mobile app isn’t the only Salesforce app that supports virtual device builds. For example, you can also use the
following instructions with Salesforce Field Service.
Note: To download packages for other apps (like Salesforce Field Service), substitute the package download URL and the iOS app
file name as specified in the other app’s documentation.
iOS
Package (ZIP) file download: sfdc.co/salesforce-mobile-app-ios-simulator
Extracted file name: Chatter.app
175
Development Tools and Processes Preview Components in the Salesforce Mobile App
Android
Package (APK) file download: sfdc.co/salesforce-mobile-app-android-emulator
SEE ALSO:
Salesforce Help: Salesforce Mobile App
Trailhead: Salesforce Mobile App Customization
176
Development Tools and Processes Preview Components in Custom Mobile Apps
177
Development Tools and Processes Preview Components in Custom Mobile Apps
• If you specify -f but not -d, the plug-in uses the value of -f to determine the file’s location.
• If you specify -f and -d, the plug-in can consider both values to determine the file’s location.
– If -f uses a relative path, the file location is calculated starting from the directory specified by -d. If -d isn’t specified, the
path is calculated against the current working directory.
– If -f specifies an absolute path, the -d value is ignored in calculating the config file location.
Example 1
-f /../../mobile-apps.json
-d /Users/jdoe/MyProject
Result /Users/mobile-apps.json
Example 2
-f /Users/jdoe/OtherProject/mobile-apps.json
-d Not specified
Result /Users/jdoe/OtherProject/mobile-apps.json
Example 3
-f /Users/jdoe/OtherProject/mobile-apps.json
-d /Users/jdoe/MyProject
Result /Users/jdoe/OtherProject/mobile-apps.json
Example 4
-f mobile-apps.json
-d Not specified
Result <current_working_directory>/mobile-app.json
If the plug-in is unable to find the config file on the calculated path, it posts an error message showing the path that failed.
VS Code usage
In VS Code, you can’t specify a custom path for the config file. VS Code always looks for mobile-apps.json in the default root
folder of the Lightning Web Components project.
SEE ALSO:
Preview Components from the Command Line
178
Development Tools and Processes Validate Lightning Web Components for Offline Use
IN THIS SECTION:
Install the Komaci Static Analyzer
The Komaci static analyser is an ESLint plugin that you install using a package manager, such as NPM or Yarn.
Troubleshoot Installation Problems
The Komaci Static Analyzer is implemented as a plugin for ESLint, a well-known JavaScript validation tool. ESLint plugins can be
finicky in their installation and configuration, requiring that all pieces are perfectly aligned for success.
Validate Components During Development
To ensure your components can be used in offline environments, watch for and act on the recommendations of the static analyzer.
Static Analyzer Validation Rules
The static analyzer validates that various code constructs and references in Lightning web components, such as wire decorators and
server calls, support offline priming. The majority of the rules focus on determining whether all code dependencies, such as imports
and modules, can be resolved; or on correct usage of offline-compatible wire adapters.
Note: Use Terminal (or your command line tool of choice) to run all commands from the root directory of your Lightning web
components project.
1. Add the Komaci Static Analyzer plugin and its dependencies to the development dependencies of your project.
NPM
npm install --save-dev @salesforce/eslint-plugin-lwc-graph-analyzer
YARN
yarn add --dev @salesforce/eslint-plugin-lwc-graph-analyzer
YARN
yarn install
179
Development Tools and Processes Troubleshoot Installation Problems
"extends": [
"@salesforce/eslint-config-lwc/recommended",
"plugin:@salesforce/lwc-graph-analyzer/recommended"
],
"overrides": [
...
Common Issues
• Install into your project — For the validation package to function properly, you must install all dependent packages using the
commands in the installation instructions from the root directory of your project. For example, the error in the preceding Output
panel screenshot indicates a missing package. This is due to not installing a package required for the project.
• Check your .eslintrc.json file — If you misconfigure your .eslintrc.json, the ESLint Output panel might show an
error related to that file. Ensure that the lines you add to your .eslintrc.json look exactly like the example in the installation
instructions and fix any syntax errors.
• ESLint must be authorized — If you don’t see any feedback in the ESLint output view, the ESLint server itself is likely not getting
initialized for your project. Make sure that you have:
– Installed theESLint extension for Visual Studio Code.
– Installed project dependencies into your project with npm install (or yarn install) from your project’s root directory.
The command installs the ESLint package and other dependencies locally to your project.
– Authorized ESLint to run in your project. If it’s not, you might see an “error” squiggly line in the first line of your JavaScript file,
indicating that ESLint isn’t authorized. Hovering over that error gives you the option to authorize it for your project.
180
Development Tools and Processes Validate Components During Development
To fix an issue, hover over the problematic code. A pop-up appears near the code, describing what the problem is and how to fix it.
• You’ll see a description of the issue, along with the linting package that found the issue.
• Click View Problem to highlight the code causing the issue, with a box underneath describing the issue and what linting package
found the issue.
• Click Quick Fix to show a dropdown of options of how to fix the issue. Then, select an option from the menu to automatically
perform that fix.
181
Development Tools and Processes Develop Offline-Ready LWCs with the LWC Offline Test
Harness
Features
• Uses the latest version of LWC Offline, with all mobile capabilities, including those in developer preview.
• Quick and convenient app flow, centered around launching LWC quick actions with a selected SObject.
• Visible draft queue, for viewing the status of pending data modification operations.
• Debug Console embedded into the app, for both a broad view of ongoing tasks and granular inspection of log messages.
• Immediate, on-demand app reloads for quickly re-bootstrapping and re-running your latest LWC code changes.
• Attach browser debuggers to view more developer-specific errors and warnings from the LWC webview.
IN THIS SECTION:
Test Harness Overview
Learn the major features and where to find them in the Test Harness app.
Install the Test Harness App
Test Harness is distributed as an installable app package, not via the Apple App Store or Google Play Store. As a developer tool, it’s
intended to be installed into and used with a working development environment. The installation process, prerequisites, and
compatibility details are consequently a bit more involved than with a normal mobile app.
Use the Test Harness App
Learn how to use the Test Harness to perform common testing and debugging actions.
Debug Lightning Web Components
The best way to develop and debug your Lightning web components is the same way you develop and debug anything built with
HTML, CSS, and JavaScript: with the built-in debugging tools in your web browser.
182
Development Tools and Processes Test Harness Overview
The sidebar menu provides access to a few duplicate or secondary features of Test Harness. Documentation for secondary features is
forthcoming.
The tabs bar along the bottom of the app’s user interface provides access to the primary features of Test Harness.
IN THIS SECTION:
Test Harness Home Tab
The Home tab of the Test Harness app is your home base for using the tool in your daily development activities. This screen is where
you start from after you log into Salesforce with the app. It provides direct access to the most essential tools in Test Harness.
Test Harness SObjects Tab
The SObjects tab of the Test Harness app is a developer-centric tool for examining Salesforce records, and the actions available on
them.
Test Harness Drafts Tab
The Drafts tab of the Test Harness app is a developer-centric tool for controlling and examining the contents of the Offline Queue,
including drafts you’ve created while offline.
183
Development Tools and Processes Test Harness Overview
Draft Control
Draft Control. As a result, you can perform actions when online, such as creating or editing a record, and give you a chance to inspect
the results before they’re uploaded to the Salesforce service. With the Draft Control card, you can only start and stop the queue and
see how many drafts are waiting in the queue. For more insight into the contents of the Offline Queue, see the Drafts tab.
The Test Harness app starts with the Offline Queue in a paused state. Drafts that you create while the queue is paused wait in the Offline
Queue until you tap Start Queue. When the queue is running, the button label changes to Stop Queue. If an error occurs while uploading
a draft, the queue is paused automatically. Once the queue is empty, it returns to a paused state.
My Offline Records
The My Offline Records card matches the same card in the Offline App in Salesforce Mobile App Plus.
Note: Your organization must purchase and license Salesforce Mobile App Plus in order to use the enhanced features. Contact
your Salesforce sales rep for more information.
My Offline Records allows you to inspect the records that are primed by the Offline Briefcase assigned to your user. You can navigate
into the list of objects that are included in the briefcase, and further into specific records.
The record view available in My Offline Records matches what your users see when using the Salesforce Mobile app in offline mode.
That is, the view is driven by your org’s metadata for page layouts, the way non-developers see them. For example, you see only the
record-specific quick actions that are added to the page layout for the object, and each quick action has the icon you’ve defined for it.
In contrast, when you view records in the developer-centric SObjects tab, all LWC-based quick actions defined for the object are
displayed in a list, without icons.
Page Refs
This is an advanced feature. It allows you to provide a list of resources to be primed by the LWC Offline engine. Each resource is specified
as a PageReference using JSON.
Warning: This tool is under development. It should be used only with guidance from a Salesforce representative.
Network Logs
This card allows you to capture and inspect details regarding the network requests made by your Lightning web components. The tool
captures requests after you tap Start, and stops capturing them when you tap Stop. To see a list of captured requests, tap Show. The
list shows the type and URL of the request, and the response code and duration. Tap a specific request to see further details, such as the
headers and body of the request and response.
LightningSDK Control
This card provides controls for affecting the LWC Offline engine. Currently, the only option is Rebootstrap. Use Rebootstrap to reload
a component under development when you’ve made changes to the component’s code. This allows you to quickly reload a custom
component, without quitting and restarting the Test Harness app.
Global Actions
This card displays quick actions that you’ve added to a global publisher layout in your org. This makes it quick and easy to test global
actions you’re working on. See Add Actions to Global Publisher Layouts in the Salesforce Help for details of how to add your global
actions to a publisher layout.
184
Development Tools and Processes Test Harness Overview
When you tap to view a record, minimal record data is displayed. The focus of this view is the list of actions available on the record. Tap
an action to run it.
The list of actions are all of the LWC-based quick actions defined for the object, whether the actions have been added to the object’s
page layout or not. This makes the SObjects tab record view a great way to quickly view new quick actions under development, without
185
Development Tools and Processes Test Harness Overview
the ceremony of adding them to a page layout, or the risk of appearing to users in your org before they’re completed. In contrast, the
record view available in My Offline Records presents a more end-user oriented view, and displays only the actions you’ve added to
the object’s page layout.
Draft Control. As a result, you can perform actions when online, such as creating or editing a record, and give you a chance to inspect
the results before they’re uploaded to the Salesforce service. With the Draft Control card, you can only start and stop the queue and
see how many drafts are waiting in the queue.
186
Development Tools and Processes Install the Test Harness App
The Test Harness app starts with the Offline Queue in a paused state. Drafts that you create while the queue is paused wait in the Offline
Queue until you tap Start Queue. When the queue is running, the button label changes to Stop Queue. If an error occurs while uploading
a draft, the queue is paused automatically. Once the queue is empty, it returns to a paused state.
Draft records in the Offline Queue are listed in the order they were created. They are local-only data, until you start the Offline Queue to
upload the draft records to the Salesforce service.
Each item in the list can be more correctly described as representing a draft operation, or instructions for applying changes, either to
create a new record or modify an existing one. The representation therefore includes details of what the operation is, and data for the
record before and after the operation is applied.
Note: Documentation regarding the format and interpretation of draft records is forthcoming.
The Edit menu allows you to Copy the JSON representation of the draft into your clipboard. Copying can be useful for pasting into a
code editor for detailed examination. You can also Delete the draft from the queue.
IN THIS SECTION:
Test Harness Prerequisites
To make full use of Test Harness, you need a complete working mobile development environment. If you haven’t set up your mobile
development tools yet, see the following resources for guidance.
Test Harness Compatibility
Test Harness is compatible with multiple versions of the Salesforce service. Some features of Test Harness can only be used with the
latest release of Salesforce. Update older versions of Test Harness to the latest release.
Download and Install — Android
Once your mobile development tools are up and running, getting started with Test Harness on Android devices is a breeze.
Download and Install — iOS
Once your mobile development tools are up and running, getting started with Test Harness on iOS virtual devices is a breeze.
Note: You don’t need to set up both Xcode and Android Studio unless you want to use Test Harness in virtual devices on both
platforms.
187
Development Tools and Processes Install the Test Harness App
3. Using Finder (macOS) or File Explorer (Windows), navigate to your Downloads folder.
4. Find the Test Harness APK file you downloaded, and drag it onto a running Android emulator.
The Test Harness app is now installed on your emulated device.
188
Development Tools and Processes Use the Test Harness App
IN THIS SECTION:
Create a Quick Action with an LWC
Quick actions are an easy way to add and launch your Lightning web components. It’s simple to add them to the Test Harness app.
Display and Run an LWC from a Quick Action
During active development, use quick actions in the Test Harness app to launch and test your Lightning web components.
After a component is deployed to Salesforce, create a Quick Action that uses it. For details, see Quick Actions in the Lightning Web
Components Developer Guide.
Tip: You don’t need to add Quick Actions to a page layout to see it in Test Harness. The Test Harness app automatically shows all
LWC-based Quick Actions for the displayed sObject type.
189
Development Tools and Processes Debug Lightning Web Components
Tip: If the list is empty, log in to the org with the same user and view a few sample records you wish to test with. Those records
are added to the Most Recently Viewed list in Salesforce. Return to Test Harness and access the sObject again by tapping on it.
The recently viewed records appear in the list.
When you tap a record, you’re presented with all of the LWC-based Quick Actions that are defined in Buttons, Links, and Actions in
Setup for the selected sObject. Tap a Quick Action to launch the LWC.
SEE ALSO:
Test Harness SObjects Tab
IN THIS SECTION:
Enable Debugging for LWC Developers
Enable debugging settings for each LWC developer user who needs to use debugging tools while developing their LWCs.
Debug in Android
Follow these steps to attach Chrome DevTools in your browser to the webview of the Test Harness app.
Debug in iOS
Follow these steps to attach Safari Web Inspector in your browser to the webview of the Test Harness app.
190
Development Tools and Processes Debug Lightning Web Components
The solution is to enable Debug Mode for users who are developing LWCs.
• In Salesforce, from Setup, enter Debug Mode in the Quick Find box, then select Debug Mode Users.
• In the user list, locate any users who need debug mode enabled.
• Enable the checkbox next to users for whom you want to enable debug mode.
More details, including a more complete description of the effects of Debug Mode, are available in “Enable Debug Mode in Salesforce”
in the Lightning Web Components Developer Guide.
SEE ALSO:
Lightning Web Components Developer Guide: Enable Debug Mode in Salesforce
Lightning Web Components Developer Guide: Debug Components in an Org With LWS Enabled
Debug in Android
Follow these steps to attach Chrome DevTools in your browser to the webview of the Test Harness app.
1. On your emulated Android device, open the Settings app.
2. Enter About emulated device into the search bar, and tap the result titled About emulated device.
3. Scroll to the bottom of the page and tap Build number seven times. The message “You are now a developer!” appears after the
seventh tap, meaning that developer mode is enabled for the emulator.
You only need to do this step once for each emulated device you use for development.
191
Development Tools and Processes Debug Lightning Web Components
For additional information on the basics of debugging with Chrome Developer Tools, see Remote debugging WebViews (Google).
For a deeper dive on debugging JavaScript in an embedded WebView of an Android mobile app, see Debugging embedded JavaScript
in an Android app using Chrome DevTools.
Debug in iOS
Follow these steps to attach Safari Web Inspector in your browser to the webview of the Test Harness app.
1. Launch Safari on your Desktop.
2. Select Safari > Preferences.
3. Select Advanced.
4. Enable Show Develop menu in menu bar. Then close the Preferences panel.
192
Development Tools and Processes Debug Your Components with Virtual Device Builds
You only need to do this step once for your development system.
5. Select Develop > Simulator - device - version, where the Simulator is the one that you’ve opened with the Test Harness app for
testing your new Lightning web component.
A window appears, showing the Safari Web Inspector developer tools connected to your simulator. You can use these tools and
standard web development techniques to refine and improve your content.
For additional information about the Web Inspector and how to use it, see Apple Web Development Tools (Apple).
Note: You can debug the web-based code of your component, but you can’t debug the platform native code of the mobile app.
Virtual device builds of the Salesforce mobile app let you preview your mobile Lightning web components on a wide range of simulated
Android and iOS devices. To install a build into a simulated device, see Preview Components in the Salesforce Mobile App on page 175.
193
Development Tools and Processes Customize the Offline Experience for the Salesforce Mobile
App
To enable Safari’s developer tools, including Web Inspector, follow these steps.
1. On your desktop development machine, open the Safari browser.
2. Select Safari > Preferences….
3. Select Advanced.
4. Enable Show Develop menu in menu bar.
Safari developer tools are located in the Develop menu, and are active until you turn them off by reversing the preceding steps.
To debug a mobile component, connect your desktop instance of Safari to the Salesforce mobile app running on your virtual device.
1. On your desktop development machine, select Safari > Develop > Simulator — device — version, where device is
the simulated hardware, and version is the operating system installed on it. For example, Simulator — iPhone 11 Pro — iOS
13.3 (17C45).
2. Select Automatically Show Web Inspector for JSContexts.
When you interact with your component in the simulated device, a new Web Inspector window opens. Use Web Inspector to debug
your component in much the same way you debug it when it’s running directly in Safari on your desktop.
To learn more about using Safari Web Inspector, see webkit.org/web-inspector/enabling-web-inspector/.
SEE ALSO:
Salesforce Help: Salesforce Mobile App
Trailhead: Salesforce Mobile App Customization
194
Development Tools and Processes Prerequisites & Setup Considerations
Note: Your organization must purchase and license Salesforce Mobile App Plus to configure and use the Offline App. Contact
your Salesforce sales rep for more information.
With the power of Lightning Web Components (LWC), you can create custom apps and experiences that tailor the Salesforce Mobile
App to your specific business needs. LWC represents the best of the Salesforce platform, bringing modern web standards in performant,
modular components that are easy to create. The goal of Mobile Offline with LWC is to help you build mobile experiences that work
regardless of network conditions.
The Offline App is a pro-code solution that lets users configure LWCs for mobile offline experiences. The Offline App Developer Starter
Kit, which is a publicly available GitHub repository, provides the resources to customize the offline experience. To make the development
and set up process easier, we created a tool called the Offline App Onboarding Wizard. The Offline App Onboarding Wizard guides you
with easy-to-follow prompts to configure the Offline Starter Kit experiences for the Offline App.
IN THIS SECTION:
Prerequisites & Setup Considerations
You need the correct tools installed to use the Offline App Onboarding Wizard. If you haven’t set up your tools yet, see the following
resources for guidance.
Download and Install
After you’ve gotten your development tools up and running, getting started with the Offline App Onboarding Wizard is a breeze.
Configure the Offline Experience
In this section, we provide supplemental information on configuring your offline experience.
195
Development Tools and Processes Configure the Offline Experience
Continue to use the Onboarding Wizard to set up and deploy your offline configurations.
IN THIS SECTION:
1. Build a Briefcase
Briefcase Builder is how you choose which records are available offline for your users. It's important to think about your users and
which records they need access to while offline. The Offline App uses and depends on a Briefcase to use when priming records for
offline use.
2. Select a Landing Page Template
The Landing Page is the Mobile Offline home page for the Salesforce Mobile App. When a user logs into the Salesforce Mobile App
offline experience, the landing page is the first thing they see. This page is intended to give access to the user’s most important
records and allow them to quickly and easily take relevant actions.
3. Generate and Configure LWC Quick Actions
The Onboarding Wizard can generate missing LWC quick actions based on the sObjects that are configured in your landing page
template selection.
4. Deploy Your Configurations
Before you can run a quick action based on a Lightning web component, you need to deploy the relevant code artifacts to your org.
Components and quick actions can be deployed using the Onboarding Wizard or manually with Visual Studio Code.
5. Add LWC Quick Actions to Mobile Layouts
For a quick action to appear in the action bar of a record view, it must be assigned to the main page layout for the record's object
type.
Build a Briefcase
Briefcase Builder is how you choose which records are available offline for your users. It's important to think about your users and which
records they need access to while offline. The Offline App uses and depends on a Briefcase to use when priming records for offline use.
The Onboarding Wizard takes you to the Briefcase Builder page in Salesforce Setup so you can configure a briefcase for your org.
Tips For Briefcase Use With Mobile Offline
• Consider grouping users into specific roles and choosing records that are relevant for that user group.
196
Development Tools and Processes Configure the Offline Experience
• Keep in mind that records that load on the Landing Page (Mobile Offline’s home page) rely on the Briefcase to populate the record
details.
• Ensure that all records that appear on a users Landing Page are also in their Briefcase.
For more information on building a briefcase, see Configure a Briefcase in the Salesforce Help.
197
Development Tools and Processes Configure the Offline Experience
Each landing page template has specific objects and quick actions.
• Default
– Accounts
– Contacts
– Opportunities
• Case Management
– New Case action
– 5 most recent Cases
– 5 most recent Accounts
– 5 most recent Contacts
• Healthcare
– BarcodeScanner action
– New Visit action
– New Visitor action
– Visit object
• Retail Execution
– New Opportunity action
– New Lead action
– New Account action
For more information on updating the landing_page.json file, see Customize The Landing Page in the Salesforce Help.
198
Development Tools and Processes Configure the Offline Experience
Review the missing LWC quick actions, and click Generate LWC Quick Actions.
The Onboarding Wizard adds the generated quick actions to the Offline App Starter Kit lwc and quickactions folder.
In Visual Studio Code, right-click on a component or quick action and select SFDX Command: Deploy Source to Org. This action
pushes your Offline Starter Kit project configurations for the LWC Quick Actions upstream to the Salesforce org that’s connected via your
Visual Studio Code development environment.
199
Development Tools and Processes Configure the Offline Experience
Note: You might need to clear caches, and quit and restart the app before changes to LWCs are active.
Here's an example of assigning the Edit quick action for the Account object type:
1. From Setup, open the Object Manager.
2. Enter Account in the Quick Find box, then select Account.
3. From the Account object management settings, go to Page Layouts and click Account Layout.
200
Development Tools and Processes Configure the Offline Experience
4. In the Salesforce Mobile and Lightning Experience Actions panel, if you see a link to override the predefined actions, the page
layout is using the default actions. Click the link to enable customizing the actions.
At this time, only actions added to the main page layout are accessible in the Offline App. Support for record types will be available in
a future release.
201
CHAPTER 8 Quick Start Tutorials
In this chapter ... These hands-on tutorials get you started with creating custom LWCs for your mobile apps.
• Develop a Lightning
Web Component
Quick Action
• Debug Lightning Web
Components in the
Field Service Mobile
App
202
Quick Start Tutorials Develop a Lightning Web Component Quick Action
IN THIS SECTION:
Prerequisites
Ensure you’re ready for this tutorial by verifying that you have the right software installed and configured, and your org has Lightning
web components enabled for mobile users.
Field Service Org Setup
Create a permission set with the Access Lightning Web Components in Field Service Mobile permission,
and assign this permission set to users who develop for or use Lightning web components in the mobile app.
iOS Simulator Setup
During development it’s convenient to test your code in a virtual device. Use Xcode to create a device simulator, and install the
virtual device build of your mobile app into it.
Android Emulator Setup
During development it’s convenient to test your code in a virtual device. Use Android Studio to create a device emulator, and install
the virtual device build of your mobile app into it.
Workspace Setup
Set up your development environment, create a project to develop your LWC in, and connect your project to Salesforce.
Create and Configure a Lightning Web Component
In this section, you’ll create a basic component named demoLWCAction that displays a “Hello World!” message on the screen.
Prerequisites
Ensure you’re ready for this tutorial by verifying that you have the right software installed and configured, and your org has Lightning
web components enabled for mobile users.
• Salesforce CLI is installed and up-to-date.
• VS Code is installed and up-to-date.
• Salesforce Extension Pack for VS Code is installed and up-to-date.
Note: Ensure all prerequisites listed on the extension pack page are also satisfied.
Note: This step is required for Field Service orgs. If you’re using LWC Offline in the Salesforce mobile app, skip to the next step.
203
Quick Start Tutorials Field Service Org Setup
Lightning web components for LWC Offline-enabled mobile apps is an opt-in feature. To enable it for your org, you must create and
assign a permission set for your mobile users that includes enabling the Access Lightning Web Components in Field
Service Mobile permission. This permission set is required to access and run LWCs within the Field Service mobile app. (While
not technically required to develop LWCs, you’ll have a hard time developing components when you can’t run them.)
You can use this one permission set for any number of Lightning web components and mobile users.
IN THIS SECTION:
Define a Permission Set for Your Org
Create a permission set that applies the permissions required to enable Lightning web components to users with the permission
set.
Assign the Permission Set to a Mobile User
Assign the permission set that enables Lightning web components to users who must use or develop LWCs.
3. Click Save.
4. In the Find Settings box, enter Access Lightning Web Components in Field Service Mobile and click it.
5. Click Edit.
6. Select the Access Lightning Web Components in Field Service Mobile checkbox.
7. Click Save.
6. Click Assign.
204
Quick Start Tutorials iOS Simulator Setup
IN THIS SECTION:
Configure Minimum Required iOS Simulator Settings
Ensure your virtual device meets the minimum device and iOS version requirements to run your mobile app.
Install the Field Service App for iOS
To run the Field Service mobile app in an iOS simulator, download and install a virtual device build of the app. After it’s installed,
open the app and log into your development org.
After the device simulator launches you can close Xcode, but keep the Simulator app’s window open to install the Field Service app in
the next section.
5. Click (simulator tap, you get the idea) the Field Service app. Click Get Started.
6. Click the screen to run through the tutorial or click Skip.
205
Quick Start Tutorials Android Emulator Setup
Warning: If you’re logging in as a community user for the first time, click to add a new connection.
• For Host, enter your org’s URL in the following format: https://[yourURL].my.salesforce.com.
• For Label, enter a nickname for your connection.
IN THIS SECTION:
Configure Minimum Required Android Emulator Settings
Ensure your virtual device meets the minimum device and Android API version requirements to run your mobile app.
Install the Field Service App for Android
To run the Field Service mobile app in an Android emulator, download and install a virtual device build of the app. After it’s installed,
open the app and log into your development org.
206
Quick Start Tutorials Android Emulator Setup
207
Quick Start Tutorials Android Emulator Setup
2. Drag the downloaded .apk file into the Android Emulator window.
3. Click a blank space on the Android Emulator’s screen and drag up to view the installed apps.
4. Click the newly installed Field Service app.
5. Click I Agree to accept the Order Form Supplement agreement.
208
Quick Start Tutorials Workspace Setup
6. Click the vertical dots button on the top right and select Change Server.
7. Select a connection.
Warning: If you’re logging in as a community user for the first time, click Add New Connection, fill in the form as indicated
in the following bullet list, and then click Apply to save the changes.
• For Name, enter a nickname for your connection.
• For URL, enter your org’s URL. It must be in the following format: https://[yourURL].my.salesforce.com
8. Click the arrow in the top left to go back to the login screen.
9. Enter your username and password for your org.
10. Click Log In.
11. Click Allow to allow the app to access your Salesforce information.
12. Click through the various permissions screens and allow them the appropriate access.
When finished, you arrive at the app’s home screen.
Workspace Setup
Set up your development environment, create a project to develop your LWC in, and connect your project to Salesforce.
1. Launch VS Code.
2. Select File > Open and open a project to use with your org.
Note: If you don’t have a project created, you can open the VS Code Command Palette by clicking View > Command Palette,
enter SFDX, and select SFDX: Create a Project. Then follow the prompts.
3. In the menu bar, select View > Terminal to open VS Code’s integrated terminal if it’s not already visible.
209
Quick Start Tutorials Create and Configure a Lightning Web Component
4. Run the following command to install the Salesforce Extension Plugins for mobile.
sf plugins install @salesforce/lwc-dev-mobile
5. In the menu bar, select View > Command Palette to open the VS Code Command Palette.
6. Enter SFDX and select SFDX: Authorize an Org.
7. Select the org you want to use and press Enter.
A web page opens for the org login.
8. Verify your org authorization by checking the bottom left in VS Code.
You should see your username in the VS Code status bar.
If you have difficulty authorizing SFDX for access to your org, see SFDX Authorization.
IN THIS SECTION:
Create and Deploy a Lightning Web Component to Salesforce
Create a simple Lightning web component, configure its metadata, and then deploy the component to your Salesforce org—all
from within VS Code.
Verify the Component Was Deployed to Your Org
The simplest way to verify that a Lightning web component is available in your org is to view the list of components in Setup in
Salesforce.
Create a Quick Action in Salesforce
To access your Lightning web component, you must assign your component to a new Quick Action, and then assign the Quick
Action to a page layout in Salesforce. This configuration makes it visible in the Actions launcher in the mobile app.
Add the Quick Action to a Page Layout in Salesforce
Make a Lightning web component quick action available in the mobile app by adding it to the mobile actions section of a page
layout.
Clear Cached Metadata
To see changes to a Lightning web component as you develop, cached metadata must be cleared in the mobile app. Clear cached
metadata every time new code is deployed to the org to see your changes.
Run the Quick Action in the Mobile App
Let’s finally see that Lightning web component working in the Field Service mobile app.
210
Quick Start Tutorials Create and Configure a Lightning Web Component
4. In the newly created demoLWCAction.js-meta.xml, replace the default code with the following and save the file:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>56.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordAction</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordAction">
<actionType>ScreenAction</actionType>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
5. In the VS Code explorer, right-click the force-app/main/default/lwc/demoLWCAction folder and select SFDX:
Deploy Source to Org.
211
Quick Start Tutorials Create and Configure a Lightning Web Component
212
Quick Start Tutorials Create and Configure a Lightning Web Component
5. Click Save.
6. Click Service Appointment next to Object Name to return to the Service Appointment object page.
Note: Mobile quick actions are only added to the mobile layout. You can’t verify that mobile quick actions were successfully
added to the correct page layout using the desktop experience.
213
Quick Start Tutorials Create and Configure a Lightning Web Component
Android
214
Quick Start Tutorials Create and Configure a Lightning Web Component
iOS
Android
215
Quick Start Tutorials Debug Lightning Web Components in the Field Service Mobile
App
iOS
IN THIS SECTION:
Install Local Development Server Plugin
Whether you’re debugging your component for iOS or Android, you must first install the LWC Development Server for mobile.
Debug in iOS
Connect Safari Web Inspector on your desktop to the WebView in the Field Service mobile app where your LWC is running.
Debug in Android
Connect Chrome DevTools on your desktop to the WebView in the Field Service mobile app where your LWC is running.
216
Quick Start Tutorials Debug in iOS
Note: If you encounter an error when updating Salesforce CLI, see Update Salesforce CLI for troubleshooting instructions.
2. In the same terminal window, run the following command to install the LWC Development Server for mobile.
sf plugins install @salesforce/lwc-dev-server
Debug in iOS
Connect Safari Web Inspector on your desktop to the WebView in the Field Service mobile app where your LWC is running.
Note: Debugging in iOS currently only works with Big Sur or later, and requires using the Safari Technology Preview browser.
See Apple Web Development Tools for additional information about the Web Inspector and how to use it.
217
Quick Start Tutorials Debug in Android
Debug in Android
Connect Chrome DevTools on your desktop to the WebView in the Field Service mobile app where your LWC is running.
1. On your emulated Android device, open the Settings app.
2. Enter About emulated device into the search bar and click it.
3. Scroll to the bottom of the page and click Build number seven times.
The message “You are now a developer!” appears when you click it enough, indicating that developer mode is enabled for the
emulator.
4. Launch Chrome on your desktop.
5. In the location bar, enter chrome://inspect/#devices.
6. Click Inspect for the WebView under the Remote Target emulator you’re using.
A window appears containing your emulator with Chrome DevTools connected to it. You can use Chrome DevTools to inspect the LWC
element, set breakpoints, and see the console output. As with iOS, you can use the standard web development techniques for working
with HTML, JavaScript, and CSS to run, test, debug, and improve your LWC.
218
Quick Start Tutorials Debug in Android
See Remote debugging WebViews for additional basics, and Debugging embedded JavaScript in an Android app using Chrome DevTools
for a deep dive on debugging JavaScript in an embedded WebView of an Android mobile app.
219