How to Create an Angular Barcode QR Code Scanning Library
Tags: webdev, angular, typescript, qrcode
Published: 2022-06-28 09:16:24

Previously, we created an [Angular Barcode and QR Code Scanner](https://www.dynamsoft.com/codepool/angular-barcode-qr-code-scanner.html). To make it reusable for other Angular applications, we can turn it into an Angular library. This article will show you the process of creating an Angular barcode QR code scanning library, as well as how to integrate it into your Angular application.

## Download ngx-barcode-qrcode-sdk
[https://www.npmjs.com/package/ngx-barcode-qrcode-sdk](https://www.npmjs.com/package/ngx-barcode-qrcode-sdk)

```bash
npm i ngx-barcode-qrcode-sdk
```

## Steps to Create an Angular Library for Dynamsoft JavaScript SDK
The [official Angular tutorial](https://angular.io/guide/creating-libraries) guides you to generate a new library skeleton in a new workspace without containing an Angular application.

```bash
ng new my-workspace --no-create-application
cd my-workspace
ng generate library my-lib
```

However, to develop and debug an Angular library conveniently, it is better to scaffold a library project in an Angular application.

Our goal is to migrate the Angular `Barcode Reader` and `Barcode Scanner` components from the existing Angular barcode QR code scanner application into an Angular library. So get the source code and generate the library project as follows:

```bash
git clone https://github.com/yushulx/angular-barcode-qr-code-scanner.git
cd angular-barcode-qr-code-scanner
ng generate library ngx-barcode-qrcode-sdk
```

Afterwards, copy `barcode-reader` and `barcode-scanner` folders to `projects/ngx-barcode-qrcode-sdk/src/lib`. According to the Angular library naming convention, we rename the folders to `ngx-barcode-reader` and `ngx-barcode-scanner`.

To access Dynamsoft JavaScript SDK from the Angular library, we need to add it as a peer dependency in `package.json`.

```json
"peerDependencies": {
    ...
    "dynamsoft-javascript-barcode": "^9.0.2"
  },
```

An angular library consists of service, component and module. Open the `public-api.ts` file to export the APIs of the library.

```typescript
export * from './lib/ngx-barcode-qrcode-sdk.service';
export * from './lib/ngx-barcode-reader/ngx-barcode-reader.component';
export * from './lib/ngx-barcode-scanner/ngx-barcode-scanner.component';
export * from './lib/ngx-barcode-qrcode-sdk.module';
```

A module is the entry point of the library. In `ngx-barcode-qrcode-sdk.module.ts`, we declare Angular components and use the Angular service to store the global configurations of Dynamsoft JavaScript Barcode SDK.

```typescript
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { NgxBarcodeReaderComponent } from './ngx-barcode-reader/ngx-barcode-reader.component';
import { NgxBarcodeScannerComponent } from './ngx-barcode-scanner/ngx-barcode-scanner.component';
import { BarcodeQrcodeSdkServiceConfig } from './ngx-barcode-qrcode-sdk.service';

@NgModule({
  declarations: [
    NgxBarcodeReaderComponent,
    NgxBarcodeScannerComponent,
  ],
  imports: [
  ],
  exports: [
    NgxBarcodeReaderComponent,
    NgxBarcodeScannerComponent,
  ]
})
export class NgxBarcodeQrcodeSdkModule {
  constructor(@Optional() @SkipSelf() parentModule?: NgxBarcodeQrcodeSdkModule) {
    if (parentModule) {
      throw new Error(
        'GreetingModule is already loaded. Import it in the AppModule only');
    }
  }

  static forRoot(config: BarcodeQrcodeSdkServiceConfig): ModuleWithProviders<NgxBarcodeQrcodeSdkModule> {
    return {
      ngModule: NgxBarcodeQrcodeSdkModule,
      providers: [
        { provide: BarcodeQrcodeSdkServiceConfig, useValue: config }
      ]
    };
  }
}
```

The configurations include the license key and the resource path, which are defined in `ngx-barcode-qrcode-sdk.service.ts`.

```typescript
import { Injectable, Optional } from '@angular/core';
import { BarcodeReader } from 'dynamsoft-javascript-barcode';

export class BarcodeQrcodeSdkServiceConfig {
  licenseKey = '';
  resourcePath = '';
}

@Injectable({
  providedIn: 'root'
})
export class NgxBarcodeQrcodeSdkService {

  constructor(@Optional() config?: BarcodeQrcodeSdkServiceConfig) { 
    if (config) { 
      BarcodeReader.license = config.licenseKey;
      BarcodeReader.engineResourcePath = config.resourcePath;
    }
  }
}
```

There is no more to do for the two `ngx-barcode-reader` and `ngx-barcode-scanner` components except add the `@Output()` decorator, which lets the decoding results flow from the child component to a parent component.


**barcode-reader**

```typescript
export class NgxBarcodeReaderComponent implements OnInit {
  @Output() result = new EventEmitter<string>();
  ...

  this.reader.decode(file).then((results: any) => {
          console.log(results);
          let txts: any = [];
          try {
            let localization;
            if (results.length > 0) {
              for (var i = 0; i < results.length; ++i) {
                txts.push(results[i].barcodeText);
                localization = results[i].localizationResult;
                this.overlayManager.drawOverlay(
                  localization,
                  results[i].barcodeText
                );
              }

              this.result.emit(txts.join(', '));
            } else {
              this.result.emit(txts.join(', '));
            }
          } catch (e) {
            alert(e);
          }
        });
  ...
}
```

**barcode-scanner**

```typescript
export class NgxBarcodeScannerComponent implements OnInit {
  @Output() result = new EventEmitter<string>();
  ...

  this.scanner.onFrameRead = results => {
        ...

        let txts: any = [];
        try {
          let localization;
          if (results.length > 0) {
            for (var i = 0; i < results.length; ++i) {
              txts.push(results[i].barcodeText);
              localization = results[i].localizationResult;
              this.overlayManager.drawOverlay(localization, results[i].barcodeText);
            }
            this.result.emit(txts.join(', '));
          }
          else {
            this.result.emit(txts.join(', '));
          }

        } catch (e) {
          alert(e);
        }
      };
  ...
}
```

So far, the Angular barcode QR code scanning library is done. In the following sections, you will see how to use the library in an Angular application.

## How to Build Angular Barcode QR Code Scanner with the Library
Since we have moved all heavy work to the library, building an Angular barcode QR code scanner becomes much simpler.
1. In your Angular application workspace, install the Angular library via npm command in terminal:

    ```bash
    npm i ngx-barcode-qrcode-sdk
    ```

    As the installation is done, you need to configure the resource path in `angular.json` file.
    ```json
    "build": {
        "builder": "@angular-devkit/build-angular:browser",
        ...
        "assets": [
            "src/favicon.ico",
            "src/assets",
            {
            "glob": "**/*",
            "input": "./node_modules/dynamsoft-javascript-barcode/dist",
            "output": "assets/dynamsoft-javascript-barcode"
            }
        ],
        ...
    }
    ```
2. Import the library in the `app.module.ts` file:

    ```typescript
    import { NgxBarcodeQrcodeSdkModule } from 'ngx-barcode-qrcode-sdk';

    ...
    @NgModule({
      ...
      imports: [
        ...
        NgxBarcodeQrcodeSdkModule.forRoot({ licenseKey: "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==", resourcePath: "assets/dynamsoft-javascript-barcode/" }),
      ],
      ...
    })

    ...
    ```

    You need to apply for a [30-day free trial license key](https://www.dynamsoft.com/customer/license/trialLicense?product=dbr) to activate Dynamsoft JavaScript Barcode Reader. The resource path should be the same as the one in the `angular.json` file.

3. In your component `*.ts` file, inject the `NgxBarcodeQrcodeSdkService` and add the output event:

    ```typescript
    import { NgxBarcodeQrcodeSdkService } from 'ngx-barcode-qrcode-sdk';
    ...
    export class FooComponent implements OnInit {
      barcodeResult: string = '';
      constructor(private barcodeQrCodeSdkService: NgxBarcodeQrcodeSdkService) {
      }

      ngOnInit(): void {
      }

      onResultReady(result: string): void {
        this.barcodeResult = result;
      }
    }
    ```

4. Then in corresponding HTML file, include `ngx-barcode-reader` or `ngx-barcode-scanner`:

    **Barcode Reader**
    ```html
    <div>
      <a>Barcode QR code decoding results: {{barcodeResult}}</a>
    </div>

    <ngx-barcode-reader
    (result)="onResultReady($event)"
    ></ngx-barcode-reader>
    ```

    ![Angular barcode QR code reader](https://www.dynamsoft.com/codepool/img/2022/06/angular-barcode-qrcode-reader-library.png)

    **Barcode Scanner**
    ```html
    <div>
      <a>Barcode QR code decoding results: {{barcodeResult}}</a>
    </div>

    <ngx-barcode-scanner
    (result)="onResultReady($event)"
    ></ngx-barcode-scanner>
    ```

    ![Angular barcode QR code scanner](https://www.dynamsoft.com/codepool/img/2022/06/angular-barcode-qrcode-scanner-library.png)

## Source Code
[https://github.com/yushulx/ngx-barcode-qrcode-sdk](https://github.com/yushulx/ngx-barcode-qrcode-sdk)