There are many use cases requiring to generate barcodes and QR codes in Angular applications on the fly.
In the Angular ecosystem, there are several libraries that can help you generate barcodes and QR codes. They are frequently based on popular libraries like ZXing. or JsBarcode.
One of the most promising libraries for generating barcodes and QR codes in Angular is zxing-wasm.
It is a C++ implementation of the ZXing barcode library compiled to WebAssembly (WASM). It is fast and efficient and can be used in both the browser and Node.js.
In this article, we will show how to use zxing-wasm
to render barcodes and QR codes in an Angular demo application.
We are using Angular v19 in this article to benefit from the elegance of the new resource API. However, the code should work with some adaptions also with older Angular versions as well.
BarcodeService: Generating the barcodes and QR codes
BarcodeService
is a service that generates barcodes and QR codes. It uses the writeBarcodeToImageFile
from zxing-wasm/writer
.
writeBarcodeToImageFile
has two parameters:
- the text to be encoded
- some options for the writer, the most important is the
format
which can be one of"Aztec"
,"Codabar"
,"Code128"
,"Code39"
,"Code93"
,"DataMatrix"
,"EAN-13"
,"EAN-8"
,"ITF"
,"PDF417"
,"QRCode"
,"UPC-A"
,"UPC-E"
. We only use the format in this example.
Please note that the writeBarcodeToImageFile
function returns a promise that resolves to an object with the following properties:
error
is an error message if an error occurredimage
is aBlob
object with the image data
The BarcodeService
has a method getBarcodeImage
that takes the text and the writer options as parameters and returns a promise that resolves to a SafeUrl
or null
.
The source code is depicted below.
import { inject, Injectable } from '@angular/core';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { writeBarcodeToImageFile, WriterOptions } from "zxing-wasm/writer";
/**
* Service to generate barcode images using ZXing WASM
*/
@Injectable({
providedIn: 'root'
})
export class BarcodeService {
/**
* DI
*/
private readonly sanitizer = inject(DomSanitizer);
/**
* Method to get barcode image as DataURL
* @param text is the text to encode
* @param writerOptions are the options for the writer
* @returns a promise that resolves to a DataURL as SafeUrl or null
*/
async getBarcodeImage(text: string, writerOptions?: WriterOptions): Promise<SafeUrl | null> {
if (!text || text.length === 0) {
return null;
}
const writeResult = await writeBarcodeToImageFile(text, writerOptions);
if (writeResult.error) {
console.error('BarcodeService, getBarcodeImage, error:', writeResult.error);
return null;
} else if (!writeResult.image) {
console.error('BarcodeService, getBarcodeImage, no image');
return null;
} else {
return this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(writeResult.image));
}
}
}
BarcodeComponent: Rendering barcodes and QR codes to the DOM
BarcodeComponent
is a component that renders barcodes and QR codes to the DOM. It uses the BarcodeService
to generate the barcode images.
The BarcodeComponent
has two required input signals:
text
is the text to encode as a string.format
is the format of the barcode. It can be one of"Aztec"
,"Codabar"
,"Code128"
,"Code39"
,"Code93"
,"DataMatrix"
,"EAN-13"
,"EAN-8"
,"ITF"
,"PDF417"
,"QRCode"
,"UPC-A"
,"UPC-E"
.
The BarcodeComponent
has a resource signal image
that loads the barcode image using the BarcodeService
.
The source code is depicted below.
import { ChangeDetectionStrategy, Component, inject, input, resource } from '@angular/core';
import { WriteInputBarcodeFormat } from 'zxing-wasm';
import { BarcodeService } from '../../services/barcode.service';
/**
* Component to display a barcode image
*/
@Component({
selector: 'app-barcode',
templateUrl: './barcode.component.html',
styleUrl: './barcode.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BarcodeComponent {
/** DI */
public barcodeService = inject(BarcodeService);
/**
* Required input signal providing the text to encode as string
*/
text = input.required<string>();
/**
* Required input signal providing the format of the barcode
*/
format = input.required<WriteInputBarcodeFormat>();
/**
* Barcode image resource, a DataURL as SafeUrl
*/
image = resource({
loader: () => {
return this.barcodeService.getBarcodeImage(this.text(), { format: this.format() });
}
});
}
The template of the BarcodeComponent
is simple and depicted below.
<div class="barcode">
<img [src]="image.value()" alt="barcode" />
</div>
<div class="caption">
{{ text() }}
</div>
<div class="caption">{{ format() }}</div>
AppComponent: Using the BarcodeComponent
The AppComponent
is the root component of the Angular demo application. It uses the BarcodeComponent
to render barcodes and QR codes to the DOM.
The standalone
component imports the BarcodeComponent
and uses it in the HTML template to render barcodes and QR codes for all available formats.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { BarcodeComponent } from './components/barcode/barcode.component';
@Component({
selector: 'app-root',
imports: [BarcodeComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
}
The HTML template of the AppComponent
below depicts the usage of BarcodeComponent
.
It renders barcodes and QR codes for all available formats to the DOM.
<app-barcode text="The quick brown fox jumps over the lazy dog" format="Aztec"/>
<app-barcode text="31117013206375" format="Codabar"/>
<app-barcode text="Angular" format="Code128"/>
<app-barcode text="Material" format="Code39"/>
<app-barcode text="Design" format="Code93"/>
<app-barcode text="Reactive" format="DataMatrix"/>
<app-barcode text="4001513007704" format="EAN-13"/>
<app-barcode text="96385074" format="EAN-8"/>
<app-barcode text="1234567895" format="ITF"/>
<app-barcode text="https://advenage.com" format="QRCode"/>
<app-barcode text="03600029145" format="UPC-A"/>
<app-barcode text="02345673" format="UPC-E"/>
<app-barcode text="4001513007704" format="PDF417"/>
With some simple styling, the result in the browser looks like depicted below.