Scan Barcodes Natively on a Mobile Device using LWC

A Lightning web component can use a mobile device’s camera and mobile OS platform features to scan a barcode, such as a UPC symbol or QR code. When a barcode is successfully scanned, the data that was read from the barcode is returned to the Lightning web component that invoked it. 

Scanning is performed locally on the mobile device, and doesn’t need a network connection. BarcodeScanner does require access to platform-specific APIs that are available only within compatible Salesforce mobile apps.

Scan Barcode on Mobile

Important IMPORTANT BarcodeScanner does not and cannot function when running in a web browser, whether running on a desktop or mobile device.

Salesforce has recently released a new Barcode API which supports barcode scanning natively on LWC for mobile devices. As it’s supported natively, we don’t need to worry about maintaining 3rd party Javascripts, Locker services, performance issues, etc.

Implementation:

The barcode API allows us to scan the barcodes natively using LWC. The scanning can be done in two ways
  1. Single Scanning
  2. Continuous Scanning
For the demo purpose and understanding how the Barcode API works, we will focus on Single Scanning only and then this can be extended to Continuous Scanning on demand basis.

Pre-requisites:

    • You need to have a salesforce1 mobile app installed in your mobile
    • You need a login account on Salesforce(Prod/Dev/Sandbox)

      Steps:

      1. Create a LWC component
      2. Create a Lightning Tab 
      3. Demo
      Now let's deep dive into the implementation steps.

        1. Create a LWC component: First step is to create a LWC component named barcodeScanner
          • barcodeScanner.html
          • <template>
                <div class="slds-card">
                    <div class="slds-text-align_center">
                        <span class="slds-text-heading_large">BarcodeScanner: Single Scan</span>
                    </div>
            
                    <!-- After a barcode is successfully scanned, its value is displayed here: -->
                    <template if:true={scannedBarcode}>
                        <div class="slds-var-m-vertical_large slds-var-p-vertical_medium 
                            slds-text-align_center slds-border_top slds-border_bottom">
                            Scanned barcode value is:<br/>
                            <span class="slds-text-heading_small">{scannedBarcode}</span>
                        </div>
                    </template>
            
                    <!-- Static help text -->
                    <div class="slds-text-align_center slds-text-color_weak slds-m-vertical_large">
                        Click <strong>Scan Barcode</strong> to open a barcode scanner camera view. Position a
                        barcode in the scanner view to scan it.
                    </div>
            
                    <!-- The click-to-scan button; Disabled if BarcodeScanner isn't available -->
                    <div class="slds-align_absolute-center slds-m-vertical_large">
                        <lightning-button
                            variant="brand"
                            class="slds-var-m-left_x-small"
                            disabled={scanButtonDisabled}
                            icon-name="utility:scan"
                            label="Scan Barcode"
                            title="Open a camera view and look for a barcode to scan"
                            onclick={handleScanBarcode}>
                        </lightning-button>
                    </div>
                </div>
            </template>
          • barcodeScanner.js:
          • import { LightningElement } from 'lwc';
            import { ShowToastEvent } from 'lightning/platformShowToastEvent';
            import { getBarcodeScanner } from 'lightning/mobileCapabilities';
            
            export default class BarcodeScanner extends LightningElement {
                myScanner;
                scanButtonDisabled = false;
                scannedBarcode = '';
            
                // When component is initialized, detect whether to enable Scan button
                connectedCallback() {
                    this.myScanner = getBarcodeScanner();
                    if (this.myScanner == null || !this.myScanner.isAvailable()) {
                        this.scanButtonDisabled = true;
                    }
                }
            
                //When Scan Barcode button is clicked, scan the barcode and read the value
                handleScanBarcode(event) {
                    event.preventDefault();
                    this.scannedBarcode = ''; // Reset scannedBarcode to empty string before starting new scan
                    const scanningOptions = {
                        barcodeTypes: [
                            this.myScanner.barcodeTypes.QR,
                            this.myScanner.barcodeTypes.EAN_8
                        ],
                        instructionText: 'Scan a QR Code',
                        successText: 'Scanning complete.'
                    };
                    this.myScanner.beginCapture(scanningOptions)
                        .then((result) => {
                            console.log(result);
            
                            /* Do something with the barcode scan value:
                               - look up a record
                               - create or update a record
                               - parse data and put values into a form etc.
                            Here, we just display the scanned value in the UI*/
                            this.scannedBarcode = result.value;
                            this.dispatchEvent(
                                new ShowToastEvent({
                                    title: 'Successful Scan',
                                    message: 'Barcode scanned successfully.',
                                    variant: 'success'
                                })
                            );
                        })
                        .catch((error) => {
                            // Handle cancellation and unexpected errors here
                            console.error('Scan Error: ' + JSON.stringify(error));
                            if (error.code == 'userDismissedScanner') {
                                // User clicked Cancel
                                this.dispatchToastEvent('Scanning Cancelled',
                                    'You cancelled the scanning session.',
                                    'error',
                                    'sticky'
                                );
                            } else { 
                                // Inform the user we ran into something unexpected
                                this.dispatchToastEvent('Barcode Scanner Error',
                                    'There was a problem scanning the barcode: ' + error.message,
                                    'error',
                                    'sticky'
                                );
                            }
                        })
                        .finally(() => {
                            console.log('#finally');
                            // Clean up by ending capture,
                            // whether we completed successfully or had an error
                            this.myScanner.endCapture();
                        });
                }
            
                dispatchToastEvent(title, errorMessage, variant, mode) {
                    const toastEvent = new ShowToastEvent({
                        title: title,
                        message: errorMessage,
                        variant: variant,
                        mode: mode
                    })
                    this.dispatchEvent(toastEvent);
                }
            }
          • barcodeScanner.js-meta.xml
          • <?xml version="1.0" encoding="UTF-8"?>
            <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
                <apiVersion>54.0</apiVersion>
                <isExposed>true</isExposed>
                <targets>
                    <target>lightning__Tab</target>
                </targets>
            </LightningComponentBundle>
        2. Create a Lightning Tab: Now create a lightning tab in our Salesforce org
          • Go to set up → Tabs

          • Click on New and select the barcodeScanner from available options and provide other details

          • Click Next and make default on for all profiles.
          • Click Save

        Demo:

        Now as we have been through all the coding required for Barcode Scanning, time to have a look how the scanning works. We have added only two supportive scanning options in our demo 
        barcodeTypes: [
            this.myScanner.barcodeTypes.QR,
            this.myScanner.barcodeTypes.EAN_8
        ],
        You can check for all the supportive code here.

        Resources:

        If you like this blog content and find inciteful, please comment and let me know.

        Comments

        1. This blog sharing really out of the box information, this time you came up with different content that's really amazing. Thank you for knowledge sharing blog. Please check if you can come with data visualization in salesforce related content.

          ReplyDelete
        2. I have browsed most of your posts. This post is probably where I got the most useful information for my research. Thanks for posting. Maybe we can see more on this. 2captcha login

          ReplyDelete

        Post a Comment