Skip to content

Latest commit

 

History

History

Hello World Sample for Angular

Angular is one of the most popular and mature JavaScript frameworks. Follow this guide to learn how to implement Dynamsoft Barcode Reader JavaScript SDK (hereafter called "the library") into an Angular application. Note that in this sample, TypeScript is used.

In this guide, we will be using dynamsoft-barcode-reader-bundle 10.4.3100.

Note:

If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a comprehensive guide that provides detailed instruction and best practices for a seamless integration into any frameworks!

Additionally, we're here to help! Please don't hesitate to contact us for any support or questions you might have.

Official sample

Preparation

Make sure you have node and Angular CLI installed.

This project was generated with Angular CLI version 17.3.7.

Quick Start

  1. Install project dependencies
npm install
  1. Build and serve the Angular app
ng serve

Then open https://localhost:4200/ to view the sample app.

Creating the sample project

In this section, we will be creating an Angular application utilizing the Dynamsoft Barcode Reader bundle sdk.

We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images.

By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it!

Create an Angular Application bootstrapped with Angular CLI

ng new my-app

On installation, you will be prompted to configure your project.
You can customize these options according to your preferences.
Below is the configuration used for this sample.

? Which stylesheet format would you like to use? CSS
? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? No

CD to the root directory of the application and install necessary libraries

cd my-app
npm install dynamsoft-barcode-reader-bundle@10.4.3100 -E

Start to implement

Add file "dynamsoft.config.ts" at the root of the app to configure libraries

/* /dynamsoft.config.ts */
import { CoreModule } from 'dynamsoft-core';
import { LicenseManager } from 'dynamsoft-license';
import 'dynamsoft-barcode-reader';

// Configures the paths where the .wasm files and other necessary resources for modules are located.
CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/";

/** LICENSE ALERT - README
 * To use the library, you need to first specify a license key using the API "initLicense()" as shown below.
 */

LicenseManager.initLicense('DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9', true);

/**
 * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days.
 * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license.
 * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=10.4.3100&cVer=true#specify-the-license&utm_source=samples or contact [email protected].
 * LICENSE ALERT - THE END
 */

// Optional. Preload "BarcodeReader" module for reading barcodes. It will save time on the initial decoding by skipping the module loading.
CoreModule.loadWasm(['DBR']);

Note:

Generate and edit the video-capture component

  • Generate the video-capture. The video-capture component helps decode barcodes via camera.
ng generate component video-capture
  • In video-capture.component.html, add code to setup the component's HTML
<!-- /src/app/video-capture/video-capture.component.html -->
<div
  #cameraViewContainer
  class="camera-view-container"
  style="width: 100%; height: 70vh"
></div>
<br />
Results:
<div class="results">{{resultText}}</div>
  • In video-capture.component.ts, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our source code.
/* /src/app/video-capture/video-capture.component.ts */
import { Component, ElementRef, ViewChild } from '@angular/core';
import '../dynamsoft.config';
import { CameraEnhancer, CameraView } from 'dynamsoft-camera-enhancer';
import { CaptureVisionRouter } from 'dynamsoft-capture-vision-router';
import { MultiFrameResultCrossFilter } from 'dynamsoft-utility';

const componentDestroyedErrorMsg = 'VideoCapture Component Destroyed';

@Component({
  selector: 'app-video-capture',
  templateUrl: './video-capture.component.html',
  styleUrls: ['./video-capture.component.css'],
  standalone: true,
})
export class VideoCaptureComponent {
  @ViewChild('cameraViewContainer') cameraViewContainer?: ElementRef<HTMLDivElement>;
  resultText = "";

  resolveInit?: () => void;
  pInit: Promise<void> = new Promise((r) => {
    this.resolveInit = r;
  });
  isDestroyed = false;

  cvRouter?: CaptureVisionRouter;
  cameraEnhancer?: CameraEnhancer;

  async ngAfterViewInit(): Promise<void> {
    try {
      // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control.
      const cameraView = await CameraView.createInstance();
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      } // Check if component is destroyed after every async
      this.cameraEnhancer = await CameraEnhancer.createInstance(cameraView);
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }

      // Get default UI and append it to DOM.
      this.cameraViewContainer!.nativeElement.append(cameraView.getUIElement());

      // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source.
      this.cvRouter = await CaptureVisionRouter.createInstance();
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }
      this.cvRouter.setInput(this.cameraEnhancer);

      // Define a callback for results.
      this.cvRouter.addResultReceiver({
        onDecodedBarcodesReceived: (result) => {
          if (!result.barcodeResultItems.length) return;

          this.resultText = '';
          console.log(result);
          for (let item of result.barcodeResultItems) {
            this.resultText += `${item.formatString}: ${item.text}\n\n`;
          }
        },
      });

      // Filter out unchecked and duplicate results.
      const filter = new MultiFrameResultCrossFilter();
      // Filter out unchecked barcodes.
      filter.enableResultCrossVerification('barcode', true);
      // Filter out duplicate barcodes within 3 seconds.
      filter.enableResultDeduplication('barcode', true);
      await this.cvRouter.addResultFilter(filter);
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }

      // Open camera and start scanning single barcode.
      await this.cameraEnhancer.open();
      cameraView.setScanLaserVisible(true);
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }
      await this.cvRouter.startCapturing('ReadSingleBarcode');
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }
    } catch (ex: any) {
      if ((ex as Error)?.message === componentDestroyedErrorMsg) {
        console.log(componentDestroyedErrorMsg);
      } else {
        let errMsg = ex.message || ex;
        console.error(errMsg);
        alert(errMsg);
      }
    }

    // Resolve pInit promise once initialization is complete.
    this.resolveInit!();
  }

  // dispose cvRouter when it's no longer needed
  async ngOnDestroy() {
    this.isDestroyed = true;
    try {
      // Wait for the pInit to complete before disposing resources.
      await this.pInit;
      this.cvRouter?.dispose();
      this.cameraEnhancer?.dispose();
    } catch (_) {}
  }
}

Note:

If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our User Guide

Generate and edit the image-capture component

  • Generate the image-capture. The image-capture component helps decode barcodes in an image.
ng generate component image-capture
  • In image-capture.component.html, add code to setup the component's HTML
<!-- /src/app/image-capture/image-capture.component.html -->
<div class="image-capture-container">
  <div class="input-container">
    <input
      type="file"
      multiple
      (change)="captureImage($event)"
      accept=".jpg,.jpeg,.icon,.gif,.svg,.webp,.png,.bmp"
    />
  </div>
  <div class="results">{{resultText}}</div>
</div>
  • In image-capture.component.ts, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our source code.
/* /src/app/image-capture/image-capture.component.ts */
import { Component, ViewChild, ElementRef } from '@angular/core';
import '../dynamsoft.config';
import { EnumCapturedResultItemType } from 'dynamsoft-core';
import type { BarcodeResultItem } from 'dynamsoft-barcode-reader';
import { CaptureVisionRouter } from 'dynamsoft-capture-vision-router';

@Component({
  selector: 'app-image-capture',
  templateUrl: './image-capture.component.html',
  styleUrls: ['./image-capture.component.css'],
  standalone: true,
})
export class ImageCaptureComponent {
  resultText = "";

  pCvRouter?: Promise<CaptureVisionRouter>;
  isDestroyed = false;

  captureImage = async (e: Event) => {
    let files = [...((e.target! as HTMLInputElement).files as any as File[])];
    (e.target! as HTMLInputElement).value = ''; // reset input
    this.resultText = '';
    try {
      // ensure cvRouter is created only once
      const cvRouter = await (this.pCvRouter =
        this.pCvRouter || CaptureVisionRouter.createInstance());
      if (this.isDestroyed) return;

      for (let file of files) {
        // Decode selected image with 'ReadBarcodes_ReadRateFirst' template.
        const result = await cvRouter.capture(file, 'ReadBarcodes_ReadRateFirst');
        console.log(result);
        if (this.isDestroyed) return;

        // Print file name if there's multiple files
        if (files.length > 1) {
          this.resultText += `\n${file.name}:\n`;
        }
        for (let _item of result.items) {
          if (_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) {
            continue; // check if captured result item is a barcode
          }
          let item = _item as BarcodeResultItem;
          this.resultText += item.text + '\n'; // output the decoded barcode text
        }
        // If no items are found, display that no barcode was detected
        if (!result.items.length)
          this.resultText +=
            'No barcode found\n';
      }
    } catch (ex: any) {
      let errMsg = ex.message || ex;
      console.error(errMsg);
      alert(errMsg);
    }
  };

  // dispose cvRouter when it's no longer needed
  async ngOnDestroy() {
    this.isDestroyed = true;
    if (this.pCvRouter) {
      try {
        (await this.pCvRouter).dispose();
      } catch (_) {}
    }
  }
}

Add the video-capture and image-capture component to the app component

  • On the app component, we will edit the component so that it offers buttons to switch components between video-capture and image-capture.

  • In app.component.html, add the following code.

<!-- /src/app/app.component.html -->
<div class='App'>
  <div class='title'>
    <h2 class='title-text'>Hello World for Angular</h2>
  </div>
  <div class='buttons-container'>
    <button (click)="switchMode('video')" [ngStyle]="{'background-color': mode === 'video' ? 'rgb(255,174,55)' : 'white'}">Decode Video</button>
    <button (click)="switchMode('image')" [ngStyle]="{'background-color': mode === 'image' ? 'rgb(255,174,55)' : 'white'}">Decode Image</button>
  </div>
  @if (mode === 'video') {
    <app-video-capture></app-video-capture>
  } @else {
    <app-image-capture></app-image-capture>
  }
</div>
  • In app.component.ts, add the following code. For our stylesheet (CSS) specification, please refer to our source code.
/* /src/app/app.component.ts */
import { Component } from '@angular/core';
import { NgStyle } from '@angular/common';

import { ImageCaptureComponent } from './image-capture/image-capture.component';
import { VideoCaptureComponent } from './video-capture/video-capture.component';

@Component({
  selector: 'app-root',
  standalone: true,
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
  imports: [NgStyle, ImageCaptureComponent, VideoCaptureComponent],
})
export class AppComponent {
  title = 'dbrjs-angular-sample';

  mode: string = 'video';

  switchMode(value: string) {
    this.mode = value;
  }
}
  • Try running the project.
ng serve

If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the Decode Image button and select the image you want to decode. Once barcodes are found, the results will show in a dialog.

Code scaffolding

Run ng generate component component-name to generate a new component. You can also use ng generate directive|pipe|service|class|guard|interface|enum|module.

Build

Run ng build to build the project. The build artifacts will be stored in the dist/ directory.

Running unit tests

Run ng test to execute the unit tests via Karma.

Running end-to-end tests

Run ng e2e to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.

Further help - Angular

To get more help on the Angular CLI use ng help or go check out the Angular CLI Overview and Command Reference page.

Support

If you have any questions, feel free to contact Dynamsoft Support.