How to Build a Lightning Web Component to Scan Barcodes in Salesforce

In this article, we are going to create a lightning web component to scan barcodes in Salesforce, the famous CRM system, so that we can quickly input data. Dynamsoft Barcode Reader is used for barcode scanning.

Because Dynamsoft Barcode Reader uses WASM, which cannot run in Salesforce LWC by default, we need to use iframe to embed a barcode scanning web page and use postMessage to communicate between the page and the component.

Demo video:

Environment Setup

  • Install Salesforce CLI.
  • Install Visual Studio Code and extensions for Salesforce DX.

You can find the detailed guide here.

New Salesforce DX Project

Open Visual Studio Code, open the Command Palette by pressing Ctrl+Shift+P (Windows) or Cmd+Shift+P (macOS) and input SFDX to select the Create Project operation.

new project

Here, we use the standard option.

Then, run SFDX: Create Lightning Web Component to create a component named barcodeScanner.

Build a Barcode Scanning Web Page

Create a new HTML file named barcode-scanner.html with the following content. You can apply for a license here.

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Barcode Scanner</title>
  <style>
  #cameraView {
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
  }
  </style>
  <script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@10.4.2000/dist/dbr.bundle.js"></script>
</head>
<html>
<body>
  <div id="cameraView"></div>
  <script>
    let cvRouter;
    let cameraEnhancer;
    let scanning = false;
    window.addEventListener(
      "message",
      async (event) => {
        console.log("received message in iframe");
        console.log(event);
        if (event.data === "toggle") {
          toggleScanning();
        }
      },
      false,
    );

    initBarcodeScanner();
    async function initBarcodeScanner(){
      Dynamsoft.License.LicenseManager.initLicense("LICENSE-KEY");
      Dynamsoft.Core.CoreModule.loadWasm(["dbr"]);
      cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();
      let cameraView = await Dynamsoft.DCE.CameraView.createInstance();
      cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView);
      document.querySelector("#cameraView").append(cameraView.getUIElement());
      cvRouter.setInput(cameraEnhancer);

      const resultsContainer = document.querySelector("#results");
      cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => {
        console.log(result);
        window.parent.postMessage(result);
      }});
      window.parent.postMessage({initialized:true});
    }

    async function toggleScanning() {
      if (!cvRouter) {
        alert("Please wait for the initialization...");
        return;
      }
      if (!scanning) {
        await cameraEnhancer.open();
        await cvRouter.startCapturing("ReadBarcodes_Balance");
      }else{
        await cvRouter.stopCapturing();
        await cameraEnhancer.close();
      }
      scanning = !scanning;
    }
  </script>
</body>
</html>

It can open the camera to scan barcodes. It can receive messages to control the scanning status and send the barcode result back to the parent.

Add Static Resources

  1. Create a folder under the staticresources folder.
  2. Put the barcode-scanner.html into the folder.
  3. Create a metadata file named foldername.resource-meta.xml in the staticresources folder with the following content to describe the resource.

    <?xml version="1.0" encoding="UTF-8"?>
    <StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
        <cacheControl>Private</cacheControl>
        <contentType>application/zip</contentType>
    </StaticResource>
    

Implement the Lightning Web Component

Now, go to the lightning web component we created.

  1. Add elements in the HTML file.

    <template>
      <lightning-card title="Barcode Scanner">
        <lightning-button
                  label="Toggle Scanning"
                  onclick={toggleScanning}
        ></lightning-button>
        <div>
          <label>
            Barcode:&nbsp;
            <span>{barcodeValue}</span>
          </label>
        </div>
        <div class="viewer" id="viewer" style="height:500px;width:400px;"></div>
      </lightning-card>
    </template>
    
  2. When the component is mounted, append the iframe.

    import dwt from '@salesforce/resourceUrl/dwt'; //import path of the resources folder
    export default class BarcodeScanner extends LightningElement {
      initialized = false;
      dbrFrame;
        
      renderedCallback() {
        if (this.initialized) {
            return;
        }
        this.initialized = true;
        this.dbrFrame = document.createElement('iframe');
        this.dbrFrame.src = dwt + "/barcode-scanner.html";
        // div tag in which iframe will be added should have id attribute with value myDIV
        this.template.querySelector("div.viewer").appendChild(this.dbrFrame);
        // provide height and width to it
        this.dbrFrame.setAttribute("style","height:100%;width:100%;");
      }
    }
    
  3. Toggle scanning when the button is clicked by posting the message to the iframe.

    toggleScanning(){
      this.dbrFrame.contentWindow.postMessage("toggle");
    }
    
  4. Receive the barcode result.

    barcodeResult;
    window.addEventListener(
      "message",
      (event) => {
        console.log(event);
        if (event.data.barcodeResultItems) {
          this.barcodeResult = event.data.barcodeResultItems[0];
        }
      },
      false,
    );
    
  5. Display the barcode text.

    get barcodeValue() {
      if (this.barcodeResult) {
        return this.barcodeResult.text;
      }else{
        return "";
      }
    }
    

Source Code

Get the source code to have a try:

https://github.com/tony-xlh/Dynamic-Web-TWAIN-samples/tree/main/Salesforce/webTWAIN