No articles found
Try different keywords or browse our categories
Generate and Scan QR Codes in Angular
Quick guide to generating and scanning QR codes in Angular browser applications. Simple examples with ngx-qrcode and html5-qrcode.
QR codes are essential for modern web apps. Here’s how to generate and scan them in Angular.
Installation
npm install @techiediaries/ngx-qrcode
npm install html5-qrcode
Generate QR Codes
Setup Module
// app.config.ts (Angular 17+)
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes)
]
};
Component Setup
// qr-generator.component.ts
import { Component } from '@angular/core';
import { NgxQRCodeModule } from '@techiediaries/ngx-qrcode';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-qr-generator',
standalone: true,
imports: [NgxQRCodeModule, FormsModule],
templateUrl: './qr-generator.component.html',
styleUrls: ['./qr-generator.component.css']
})
export class QrGeneratorComponent {
qrData: string = 'https://example.com';
qrWidth: number = 256;
}
Template
<!-- qr-generator.component.html -->
<div class="qr-container">
<h2>Generate QR Code</h2>
<input
type="text"
[(ngModel)]="qrData"
placeholder="Enter text or URL"
class="input-field"
/>
<ngx-qrcode
[value]="qrData"
[width]="qrWidth"
errorCorrectionLevel="M"
cssClass="qr-code"
></ngx-qrcode>
<button (click)="downloadQR()">Download QR Code</button>
</div>
Download QR Code
// qr-generator.component.ts
downloadQR() {
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
if (canvas) {
const url = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.download = 'qrcode.png';
link.href = url;
link.click();
}
}
Scan QR Codes
Scanner Component
// qr-scanner.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Html5QrcodeScanner } from 'html5-qrcode';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-qr-scanner',
standalone: true,
imports: [CommonModule],
templateUrl: './qr-scanner.component.html',
styleUrls: ['./qr-scanner.component.css']
})
export class QrScannerComponent implements OnInit, OnDestroy {
private scanner: Html5QrcodeScanner | null = null;
scannedResult: string = '';
isScanning: boolean = false;
ngOnInit() {
this.initScanner();
}
initScanner() {
this.scanner = new Html5QrcodeScanner(
'qr-reader',
{
fps: 10,
qrbox: { width: 250, height: 250 }
},
false
);
this.scanner.render(
(decodedText) => this.onScanSuccess(decodedText),
(error) => this.onScanError(error)
);
this.isScanning = true;
}
onScanSuccess(decodedText: string) {
this.scannedResult = decodedText;
console.log('QR Code scanned:', decodedText);
// Stop scanning after successful scan
if (this.scanner) {
this.scanner.clear();
this.isScanning = false;
}
}
onScanError(error: any) {
// Handle scan error silently
console.warn('Scan error:', error);
}
restartScanner() {
this.scannedResult = '';
this.initScanner();
}
ngOnDestroy() {
if (this.scanner) {
this.scanner.clear();
}
}
}
Scanner Template
<!-- qr-scanner.component.html -->
<div class="scanner-container">
<h2>Scan QR Code</h2>
<div id="qr-reader"></div>
<div *ngIf="scannedResult" class="result">
<h3>Scanned Result:</h3>
<p>{{ scannedResult }}</p>
<button (click)="restartScanner()">Scan Again</button>
</div>
</div>
Styling
/* qr-generator.component.css */
.qr-container {
max-width: 500px;
margin: 0 auto;
padding: 20px;
text-align: center;
}
.input-field {
width: 100%;
padding: 12px;
margin: 20px 0;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 16px;
}
.qr-code {
margin: 20px 0;
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
button {
padding: 12px 24px;
background: #007bff;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background: #0056b3;
}
/* qr-scanner.component.css */
.scanner-container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
#qr-reader {
border: 2px solid #ddd;
border-radius: 8px;
overflow: hidden;
margin: 20px 0;
}
.result {
margin-top: 20px;
padding: 20px;
background: #f0f9ff;
border-radius: 8px;
border: 2px solid #007bff;
}
.result h3 {
margin: 0 0 10px 0;
color: #007bff;
}
.result p {
word-break: break-all;
padding: 10px;
background: white;
border-radius: 4px;
margin: 10px 0;
}
Combined Component
// qr-manager.component.ts
import { Component } from '@angular/core';
import { QrGeneratorComponent } from './qr-generator.component';
import { QrScannerComponent } from './qr-scanner.component';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-qr-manager',
standalone: true,
imports: [CommonModule, QrGeneratorComponent, QrScannerComponent],
template: `
<div class="qr-manager">
<div class="tabs">
<button
[class.active]="activeTab === 'generate'"
(click)="activeTab = 'generate'">
Generate QR Code
</button>
<button
[class.active]="activeTab === 'scan'"
(click)="activeTab = 'scan'">
Scan QR Code
</button>
</div>
<app-qr-generator *ngIf="activeTab === 'generate'"></app-qr-generator>
<app-qr-scanner *ngIf="activeTab === 'scan'"></app-qr-scanner>
</div>
`,
styles: [`
.qr-manager {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.tabs {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.tabs button {
flex: 1;
padding: 12px;
border: 2px solid #ddd;
background: white;
cursor: pointer;
border-radius: 8px;
font-size: 16px;
}
.tabs button.active {
background: #007bff;
color: white;
border-color: #007bff;
}
`]
})
export class QrManagerComponent {
activeTab: 'generate' | 'scan' = 'generate';
}
QR Code with Logo
// qr-with-logo.component.ts
import { Component } from '@angular/core';
import { NgxQRCodeModule } from '@techiediaries/ngx-qrcode';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-qr-with-logo',
standalone: true,
imports: [NgxQRCodeModule, FormsModule],
template: `
<div class="qr-logo-container">
<input
type="text"
[(ngModel)]="qrData"
placeholder="Enter URL"
/>
<div class="qr-wrapper">
<ngx-qrcode
[value]="qrData"
[width]="300"
errorCorrectionLevel="H"
></ngx-qrcode>
<img
src="/logo.png"
alt="Logo"
class="qr-logo"
/>
</div>
</div>
`,
styles: [`
.qr-wrapper {
position: relative;
display: inline-block;
}
.qr-logo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: white;
padding: 5px;
border-radius: 8px;
}
`]
})
export class QrWithLogoComponent {
qrData: string = 'https://example.com';
}
Dynamic QR Code Generation
// dynamic-qr.component.ts
import { Component } from '@angular/core';
import { NgxQRCodeModule } from '@techiediaries/ngx-qrcode';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-dynamic-qr',
standalone: true,
imports: [NgxQRCodeModule, FormsModule],
template: `
<div class="dynamic-qr">
<h3>Generate vCard QR Code</h3>
<input [(ngModel)]="name" placeholder="Name" />
<input [(ngModel)]="phone" placeholder="Phone" />
<input [(ngModel)]="email" placeholder="Email" />
<button (click)="generateVCard()">Generate vCard</button>
<ngx-qrcode
*ngIf="vCardData"
[value]="vCardData"
[width]="256"
></ngx-qrcode>
</div>
`
})
export class DynamicQrComponent {
name: string = '';
phone: string = '';
email: string = '';
vCardData: string = '';
generateVCard() {
this.vCardData = `BEGIN:VCARD
VERSION:3.0
FN:${this.name}
TEL:${this.phone}
EMAIL:${this.email}
END:VCARD`;
}
}
WiFi QR Code
// wifi-qr.component.ts
import { Component } from '@angular/core';
import { NgxQRCodeModule } from '@techiediaries/ngx-qrcode';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-wifi-qr',
standalone: true,
imports: [NgxQRCodeModule, FormsModule],
template: `
<div class="wifi-qr">
<h3>WiFi QR Code</h3>
<input [(ngModel)]="ssid" placeholder="Network Name (SSID)" />
<input [(ngModel)]="password" type="password" placeholder="Password" />
<select [(ngModel)]="encryption">
<option value="WPA">WPA/WPA2</option>
<option value="WEP">WEP</option>
<option value="nopass">No Password</option>
</select>
<button (click)="generateWiFiQR()">Generate</button>
<ngx-qrcode
*ngIf="wifiData"
[value]="wifiData"
[width]="256"
></ngx-qrcode>
</div>
`
})
export class WifiQrComponent {
ssid: string = '';
password: string = '';
encryption: string = 'WPA';
wifiData: string = '';
generateWiFiQR() {
this.wifiData = `WIFI:T:${this.encryption};S:${this.ssid};P:${this.password};;`;
}
}
Scan from File
// file-scanner.component.ts
import { Component } from '@angular/core';
import { Html5Qrcode } from 'html5-qrcode';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-file-scanner',
standalone: true,
imports: [CommonModule],
template: `
<div class="file-scanner">
<h3>Scan QR from Image File</h3>
<input
type="file"
accept="image/*"
(change)="onFileSelected($event)"
/>
<div *ngIf="result" class="result">
<h4>Result:</h4>
<p>{{ result }}</p>
</div>
<div *ngIf="error" class="error">
{{ error }}
</div>
</div>
`,
styles: [`
.result {
margin-top: 20px;
padding: 15px;
background: #d4edda;
border-radius: 8px;
}
.error {
margin-top: 20px;
padding: 15px;
background: #f8d7da;
border-radius: 8px;
color: #721c24;
}
`]
})
export class FileScannerComponent {
result: string = '';
error: string = '';
async onFileSelected(event: any) {
const file = event.target.files[0];
if (!file) return;
const html5QrCode = new Html5Qrcode('reader');
try {
const result = await html5QrCode.scanFile(file, true);
this.result = result;
this.error = '';
} catch (err) {
this.error = 'Failed to scan QR code from image';
this.result = '';
}
}
}
Routes Setup
// app.routes.ts
import { Routes } from '@angular/router';
import { QrManagerComponent } from './qr-manager.component';
export const routes: Routes = [
{ path: '', redirectTo: '/qr', pathMatch: 'full' },
{ path: 'qr', component: QrManagerComponent }
];
Permissions
Camera access requires HTTPS in production. Add to angular.json for development:
{
"serve": {
"options": {
"ssl": true
}
}
}
Error Handling
// scanner-with-errors.component.ts
handlePermissionError() {
alert('Camera permission denied. Please enable camera access.');
}
handleCameraError(error: any) {
if (error.name === 'NotAllowedError') {
this.handlePermissionError();
} else if (error.name === 'NotFoundError') {
alert('No camera found on this device.');
} else {
alert('Error accessing camera: ' + error.message);
}
}
Best Practices
- Error Correction: Use ‘H’ level for QR codes with logos (30% damage tolerance)
- Size: Minimum 256x256px for reliable scanning
- Contrast: Dark QR on light background works best
- Testing: Test on multiple devices and lighting conditions
- Permissions: Always handle camera permission errors gracefully
- Cleanup: Clear scanner in
ngOnDestroyto prevent memory leaks
Quick Reference
Generate QR:
<ngx-qrcode
[value]="data"
[width]="256"
errorCorrectionLevel="M"
></ngx-qrcode>
Scan QR:
const scanner = new Html5QrcodeScanner('reader', { fps: 10 }, false);
scanner.render(onSuccess, onError);
Download QR:
const canvas = document.querySelector('canvas');
const url = canvas.toDataURL('image/png');
Special Formats:
- URL:
https://example.com - WiFi:
WIFI:T:WPA;S:NetworkName;P:Password;; - vCard:
BEGIN:VCARD\nVERSION:3.0\n... - SMS:
SMSTO:+1234567890:Hello - Email:
mailto:test@example.com
Conclusion
Angular makes QR code generation and scanning straightforward with ngx-qrcode and html5-qrcode. Both libraries work reliably in the browser without backend dependencies.
Related Articles
Angular 21 jsPDF Example to Edit & Modify PDF Files in Browser
Learn how to integrate jsPDF with Angular 21 to create, edit, and modify PDF documents directly in the browser using standalone components and signals.
Vue.js Scan & Generate QRCodes in Browser
Quick guide to generating and scanning QR codes in Vue.js browser applications. Simple examples with qrcode.vue and html5-qrcode.
How to Integrate Mozilla PDF.js in HTML: Build a PDF Viewer in Browser
Quick guide to integrating Mozilla PDF.js into your HTML application to build a functional PDF viewer directly in the browser.