Skip to content

Repository files navigation

angularx-qrcode - Angular QR Code Generator

angularx-qrcode - a fast and easy-to-use Angular QR Code Generator library

  • Compatible with Angular 22 and Ionic
  • Under active development
  • Standalone component support
  • Ivy compiler support, AOT, SSR (Server Side Rendering)
  • Accessibility (a11y) attributes supported (alt, aria-label, title)
  • Support for images
  • Trusted and used by thousands of developers like you
  • Easy to use, sample web app included

angularx-qrcode is compatible with Ionic 3-8 and Angular 4-22 with support for the Ivy compiler. It is a drop-in replacement for the no-longer-maintained angular component ng2-qrcode and based on node-qrcode.

QR Codes generated by angularx-qrcode

Different QR Code styles: regular, with image/logo, custom colors. Generate your own QR Code here: angular qr code web app

Demo App

Try the Angular QR Code Generator online, or run the included demo locally:

# Download the project and enter its directory.
git clone https://github.com/Cordobo/angularx-qrcode.git
cd angularx-qrcode

# Use the Node.js version in .nvmrc. If you use nvm, run: nvm use
# Install the exact development dependencies recorded in the lockfile.
npm ci --ignore-scripts

# Start the demo; Angular opens it in your browser.
npm start

Open http://localhost:4200/ if your browser does not open automatically. Change the QR text, renderer, colors, or logo to see the result and its corresponding template code.

The demo source is in projects/demo-app. Its QR controls and download handlers are in generator.ts and generator.html.

To preview a production build instead:

npm run build:demo
npm run start:server

Open http://localhost:3000/. Restart the preview server after rebuilding so it serves the updated files.

Installation

Angular 22 and Ionic with angularx-qrcode 22

# npm
npm install angularx-qrcode
# yarn
yarn add angularx-qrcode
# pnpm
pnpm add angularx-qrcode

For an existing Angular 22 application, continue with the integration examples. For an older Angular major, use the version mapping and installation commands below.

Local generation, external resources, and privacy

QR payload generation happens locally in your application/browser through angularx-qrcode and its qrcode runtime dependency. qrdata does not need to be sent to a hosted angularx-qrcode QR-generation API. The hosted demo is optional; applications using the npm package do not depend on it.

With the canvas renderer, an externally hosted imageSrc can cause the browser to request that image/logo from its host. For offline operation, make the application and its dependencies available offline and use locally available image/logo resources, such as bundled assets or data URLs. A local asset URL still needs to be available through the application's offline setup.

These statements describe the library's QR-generation behavior. Network access and privacy for the consuming application also depend on its own code, resources, and services; local QR generation does not establish a privacy guarantee for the whole application.

Runtime dependencies

The published package has two direct runtime dependencies: qrcode, which generates QR output, and tslib, which supplies TypeScript runtime helpers. @angular/common and @angular/core are peer dependencies supplied by the consuming Angular application. Consult the package's package.json for the authoritative dependency versions and peer ranges, and the compatibility table for the Angular/package mapping.

Direct dependencies are not the complete installed dependency graph: dependencies can have their own transitive dependencies, and the consuming application supplies its own framework and other packages. The repository's Angular CLI, build, lint, test, and demo tooling is development tooling, separate from the published library's runtime dependencies. The library is not dependency-free.

Build a minimal Angular app

Starting from an empty directory, create an Angular 22 application and install the library:

# The filename option makes the generated files match app.component.ts below.
npx @angular/cli@22 new qr-example --standalone --routing=false --style=css --skip-tests --file-name-style-guide=2016
cd qr-example
npm install angularx-qrcode

Replace src/app/app.component.ts with this complete component. Angular already bootstraps App in the generated src/main.ts.

// File: src/app/app.component.ts
import { ChangeDetectionStrategy, Component } from '@angular/core'
import { QRCodeComponent } from 'angularx-qrcode'

@Component({
  selector: 'app-root',
  // Register the library component so <qrcode> is available in this template.
  imports: [QRCodeComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <h1>My first QR code</h1>
    <!-- Replace qrdata with the text or URL you want to encode. -->
    <qrcode qrdata="https://example.com" [width]="256" errorCorrectionLevel="M" />
  `,
})
export class App {}

Start the app:

npm start

Open http://localhost:4200/ to see the QR code. The remaining examples show how to integrate it into existing templates, update its contents, and download the result.

Usage and Example Implementations

The source for a live angularx-qrcode demo app and more examples how to implement angularx-qrcode is located in the directory projects/demo-app of this repository.

Import the component into an existing app

For Angular 19 and newer, add QRCodeComponent to your standalone component's imports. These examples target the current Angular 22 package line. Keep the imports and template content your application already needs.

The integration examples below use the conventional class name AppComponent. If you started with the minimal app above, keep its generated class name App instead, matching the import in src/main.ts.

// File: src/app/app.component.ts
import { ChangeDetectionStrategy, Component } from '@angular/core'
// Keep your other TypeScript imports here.
import { QRCodeComponent } from 'angularx-qrcode'

@Component({
  selector: 'app-root',
  imports: [
    // Keep your other component imports here.
    QRCodeComponent,
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
  templateUrl: './app.component.html',
})
export class AppComponent {
  // Keep your existing component logic here.
}

Generate a QR Code from a string

Add the QR element to your HTML template. A fixed string needs no additional state in your TypeScript component:

<!-- File: src/app/app.component.html -->
<!-- Keep your existing HTML and place the QR code where you need it. -->
<qrcode [qrdata]="'Your data string'" [width]="256" errorCorrectionLevel="M" />

Generate a QR Code from component state

Use a signal when the encoded data can change:

// File: src/app/app.component.ts
import { ChangeDetectionStrategy, Component, signal } from '@angular/core'
import { QRCodeComponent } from 'angularx-qrcode'

@Component({
  selector: 'app-root',
  imports: [QRCodeComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <!-- Read the signal with () so the QR code updates when its value changes. -->
    <qrcode [qrdata]="myAngularxQrCode()" [width]="256" errorCorrectionLevel="M" />
    <button type="button" (click)="updateQrCode()">Change QR code</button>
  `,
})
export class AppComponent {
  // Set the initial text to encode. No null value is needed.
  readonly myAngularxQrCode = signal('Your QR code data string')

  updateQrCode(): void {
    // Updating the signal generates a new QR code automatically.
    this.myAngularxQrCode.set('Your updated QR code data string')
  }
}

Download a QR Code

The online demo includes a working download example.

Getting the QR Code URL

The qrCodeURL output emits a SafeUrl for the completed render. Bind it to an anchor's href. This example uses the default canvas renderer and a PNG filename:

// File: src/app/app.component.ts
import { ChangeDetectionStrategy, Component, signal } from '@angular/core'
import { SafeUrl } from '@angular/platform-browser'
import { QRCodeComponent } from 'angularx-qrcode'

@Component({
  selector: 'app-root',
  imports: [QRCodeComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <!-- Pass each completed render URL to the handler below. -->
    <qrcode
      [qrdata]="myAngularxQrCode()"
      [width]="256"
      errorCorrectionLevel="M"
      (qrCodeURL)="onChangeURL($event)"
    />
    <!-- Show the download link once a completed QR code is available. -->
    @if (qrCodeDownloadLink(); as downloadUrl) {
      <a [href]="downloadUrl" download="qrcode.png">Download</a>
    }
  `,
})
export class AppComponent {
  readonly myAngularxQrCode = signal('Your QR code data string')
  // There is no download URL until the first render finishes.
  readonly qrCodeDownloadLink = signal<SafeUrl | null>(null)

  onChangeURL(url: SafeUrl): void {
    // Keep the latest emitted URL; the previous one is revoked by the library.
    this.qrCodeDownloadLink.set(url)
  }
}

Emitted URLs are temporary Blob/object URLs. The component revokes the previous URL before emitting its replacement and revokes the current URL when destroyed. Always use the latest emitted value. Do not persist these URLs in a database, local storage, or as permanent asset links; download the file while the URL is valid if you need a lasting copy.

Renderer capabilities

Custom finder (corner) colors/shapes, rounded modules, and configurable module merging are not supported by the installed qrcode@1.5.4 renderer in any output type. colorDark and colorLight apply to the whole symbol; cssClass styles the wrapper, not individual QR modules. These features require a different or custom renderer, not additional wrapper inputs. See the renderer styling investigation for the upstream source evidence and resolution of #181.

elementType Rendered output qrCodeURL export Center image (imageSrc) Applied accessibility inputs
canvas (default) <canvas> PNG Yes; export waits for the image to be drawn ariaLabel, title
svg Inline <svg> SVG No ariaLabel, native SVG title
img <img> with a PNG data URL PNG No alt, ariaLabel, title
url Alias for img PNG No alt, ariaLabel, title

For SVG downloads, use a .svg filename. imageHeight and imageWidth apply only to the canvas center image. Remote center images must permit cross-origin loading for canvas export. If the center image fails to load or draw, the component emits qrCodeError with code render-failure and logs a canvas error and keeps the previous rendered QR code and download URL; it does not emit an incomplete replacement. On an initial failure, no canvas is displayed. The accessibility inputs describe the rendered element; they do not change the encoded QR data.

Canvas center images use encoder-aware mask selection, never a destructive rectangular knockout. The encoder evaluates all eight legal masks using the normal QR N1–N4 penalties, then prefers more light modules underneath the logo among masks tied for the lowest penalty. This conservative optimization can leave the normal QR unchanged. It preserves the chosen error correction level, version selection, segments, payload and Reed–Solomon codewords. No payload data is silently appended or changed to manufacture optimization freedom.

imagePadding (default 0) expands the target by that many canvas pixels on each side; it does not enlarge the image or paint a background. Positive image dimensions (default 40 × 40 pixels) and non-negative finite padding are required. The centered target rounds outward to QR module boundaries using the actual canvas scale and margin. Structural modules and remainder bits are excluded, and the quiet zone is never targeted. Structural patterns remain intact in the encoded matrix; as with any image overlay, opaque logo pixels can still obscure them on the canvas.

This is a limited mask-aware fallback, not full QArt artwork or a guaranteed light rectangle. With fixed payload segments, terminator and standard pad bytes there are no free RS input bits; parity is derived, not independently editable. Transparent logo areas therefore show any remaining valid dark modules. Larger logos would require more controllable encoding freedom for full light coverage; increasing padding, version or error correction does not create arbitrary free payload bits. Full QArt would require a separate explicit API authorizing mutable payload data and exposing the resulting decoded string. See the encoding investigation.

The optimized matrix itself consumes no error-correction budget. Drawing opaque logo pixels can still damage the visible symbol, so keep logos small, choose an appropriate errorCorrectionLevel and test the final image with real scanners. The library never upgrades the selected level automatically. qrCodeURL and rendered wait for the final logo drawing, including transparent images.

Changes to title, ariaLabel, alt, or cssClass update the displayed DOM without regenerating QR data or emitting another qrCodeURL. Pending renders use the latest accessibility values when displayed. Exported URLs remain snapshots of the completed render; SVG accessibility edits affect the inline SVG until the next QR render.

cssClass applies to the inner QR wrapper. Styles targeting that wrapper belong in an application's global stylesheet because Angular's component-scoped styles do not cross the QR component boundary. The demo's generated CSS targets this wrapper with .qrcodeImage > qrcode > .yourClass and includes the host flex layout.

Render completion

(rendered) emits once for each winning QR render after its final visual is attached and qrCodeURL export succeeds. Canvas completion includes loading and drawing the center image; img/url completion includes PNG decoding. SVG is ready in the DOM. This signals readiness for capture or printing, not a browser paint-frame timestamp. Errors, superseded renders, destroyed components, SSR, and accessibility/class-only updates do not emit completion. Existing qrCodeURL subscribers still receive the export before rendered; image exports now wait for image decoding too.

import { ChangeDetectionStrategy, Component, signal } from '@angular/core'
import { QRCodeComponent } from 'angularx-qrcode'

@Component({
  selector: 'app-print-qr',
  imports: [QRCodeComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <qrcode
      qrdata="https://example.com"
      [width]="256"
      (rendered)="ready.set(true)"
      (qrCodeError)="ready.set(false)"
    />
    <button [disabled]="!ready()" (click)="print()">Print QR code</button>
  `,
})
export class PrintQrComponent {
  readonly ready = signal(false)
  print(): void {
    window.print()
  }
}

For changing payloads, reset your readiness state when requesting a new QR render.

SVG accessibility

For elementType="svg", title creates a native <title> child using safe text nodes. The SVG has role="img"; ariaLabel supplies an explicit accessible name and takes precedence over the native title. Without ariaLabel, the native title names the SVG. alt applies only to img and url, never SVG.

<qrcode qrdata="https://example.com" elementType="svg" title="Scan to visit our website"></qrcode>

Handling generation errors

Bind (qrCodeError)="onQrCodeError($event)" to react to a failure without intercepting console output. The package exports the QRCodeGenerationError type with these readonly fields:

Field Meaning
code invalid-input for rejected qrdata; render-failure for QR generation, logo loading/drawing, or export failures.
elementType The selected renderer (canvas, svg, img, or url) when that render started.
error An Error instance; non-Error rejections are wrapped. Use code for application decisions, rather than parsing the message.

In browser execution, empty qrdata, the literal string 'null', and non-string values are rejected by default. allowEmptyString permits empty and 'null' strings; an allowed empty string is encoded as a space. It does not permit non-string values. Renderer failures (including payloads rejected by qrcode) use render-failure. Canvas logo load/draw failures retain the previous visual and download URL; an initial failure leaves the placeholder empty.

Only a failure belonging to the current inputs emits this output. Failures arriving after newer inputs or component destruction are ignored, including their console logging, and cannot replace a newer successful render. Successful renders emit no error. Current failures still log for debugging. Server rendering defers both generation and input validation, so neither output fires there; see SSR scope.

Rendering Guarantees

  • Async rendering and errors are latest-input-wins. Stale completions and errors are ignored if newer inputs were received or the component was destroyed.
  • Input values are not mutated during rendering. Empty-string and QR version normalization use local render values.
  • Blob URLs emitted via qrCodeURL are lifecycle-managed and revoked on replacement/component destroy.

Testing

  • Demo app and library tests run with:
npm test -- --watch=false
  • Library behavior tests include:
    • empty-string rendering without input mutation
    • stale async render protection (newer input cannot be overwritten by older completion)

Available Parameters

Attribute Type Default Description
allowEmptyString Boolean false Allow qrdata to be an empty string
alt String null HTML alt attribute (supported by img, url)
ariaLabel String null Accessible name (all renderers)
colorDark String '#000000ff' Hex RGB/RGBA foreground (3, 4, 6 or 8 digits, optional #)
colorLight String '#ffffffff' Hex RGB/RGBA background (3, 4, 6 or 8 digits, optional #)
cssClass String 'qrcode' CSS Class
elementType String 'canvas' 'canvas', 'svg', 'img', 'url' (alias for 'img')
errorCorrectionLevel String 'M' QR Correction level ('L', 'M', 'Q', 'H')
imageSrc String null Canvas-only center image URL
imageHeight Number null Canvas-only center image height
imagePadding Number 0 Canvas-only target padding in pixels; no background clearing
imageWidth Number null Canvas-only center image width
margin Number 4 Define how much wide the quiet zone should be.
qrCodeURL EventEmitter<SafeUrl> Emits a temporary QR Code download URL
rendered OutputEmitterRef<void> Emits after the current final visual and export succeed; see render completion
qrCodeError OutputEmitterRef<QRCodeGenerationError> Emits a typed current-render failure; see error handling
qrdata String '' String to encode
scale Number 4 Scale factor. A value of 1 means 1px per modules (black dots).
title String null Native SVG title child; HTML title attribute for canvas, img, url
version Number (auto) 1-40
width Number 10 Height/Width (any value)

QR Code capacity

Capacity depends on the payload, QR version, encoding, and errorCorrectionLevel. Increasing the encoded data generally increases the number of modules and the code's density at a fixed width. See the practical guidance below when choosing dimensions and preparing payloads.

Production QR guidance

  • Payload size and dimensions: Keep qrdata as short as your use case allows. More data generally needs a more complex QR code and may require a larger rendered width so scanners can distinguish its modules. Leave version automatic unless you have a specific constraint; a fixed version may not have enough capacity for your payload and error-correction level.
  • Quiet zone: Preserve the clear border around the QR code so scanners can separate it from surrounding content. The margin option controls this quiet zone in modules and defaults to 4. Avoid cropping the border or covering it with neighboring content in your page or print layout.
  • Error correction: errorCorrectionLevel accepts L, M, Q, and H (default M). Higher levels provide more error-correction redundancy, reducing data capacity at a given version and potentially requiring a denser or larger code. Choose the level together with payload size and output dimensions; it is not a guarantee of successful scanning.
  • Logo overlays: A center logo obscures QR modules and can reduce scanability. Canvas supports imageSrc, imageWidth, and imageHeight; keep the overlay small, consider higher error correction such as Q or H, and test the exact result on real devices. No logo size/error-correction combination guarantees a readable code. See renderer capabilities for export and cross-origin image requirements.
  • Vector output: Use elementType="svg" when scalable vector output is useful, for example when resizing artwork or incorporating it into a print workflow. SVG preserves vector geometry when scaled; it does not guarantee print quality or scanability. Center-image overlays are supported only by the canvas renderer.
  • Strings and Unicode: qrdata is a string and can contain Unicode text. Encoded size depends on the text's encoding, so character count alone does not determine capacity. Applications are responsible for constructing and validating domain-specific payload formats, such as URLs, Wi-Fi configuration strings, or contact details; the component encodes the supplied string.
  • Real-world validation: Test the generated code with representative devices and scanner applications at the intended output sizes. Include actual display conditions and, when applicable, the final print material, printing process, lighting, and scanning distance. Recheck after changing payloads, colors, margins, dimensions, error correction, or logos.

AOT - Ahead Of Time Compilation

The library is built with Angular's compiler in partial compilation mode and can be consumed by Angular AOT applications. The repository's production demo build exercises this integration.

SSR - Server Side Rendering

Supported scenario: an Angular 22 application can server-render a template containing QRCodeComponent. On the server the component renders its host and empty <div class="qrcode"></div> placeholder, and defers generation and input validation. It emits neither qrCodeURL nor qrCodeError, and does not load imageSrc.

All four elementType values (canvas, svg, img, url) defer their QR visuals to browser execution. Canvas, logo loading via Image, DOM-based rendering, and Blob/object-URL exports are browser-only component features. Even SVG output is not generated by this component on the server. A normally bootstrapped browser application generates the QR code when Angular applies the component inputs. Hydration has not been validated and is not claimed by this test.

Maintainers can reproduce the supported server behavior after npm ci --ignore-scripts:

npm run test:ssr

This builds the published library and executes Angular renderApplication in Node for each renderer with Unicode and empty payloads and an external logo source. It asserts a server-rendered application and empty QR placeholder, no QR visuals, no output events, and no render errors. It uses no browser-global shims. The executable harness also runs in CI; it does not test hydration or server-side QR image generation.

Compatibility and maintenance

Normal fixes currently focus on the 22.x release line, whose peer dependencies require Angular 22. The table below records historical compatibility, not ongoing maintenance for every listed version. Older lines receive attention on a best-effort basis; fixes and security backports are not guaranteed. There is no formal LTS commitment or guaranteed support period. See the security policy for vulnerability reporting and security-fix expectations.

Angular/package compatibility mapping

Angular Version angularx-qrcode Version
^22 ^22.0.0
^21 ^21.0.5
^20 ^20.0.0
^19 ^19.0.0
^18 ^18.0.2
^17 ^17.0.1
^16 ^16.0.2
^15 ^15.0.1
^14 ^14.0.0
^13 ^13.0.15
^12 ^12.0.3
^11 ^11.0.0
^10 ^10.0.12
^9 ^2.3.7
^8 ^2.1.4
^5 / ^6 / ^7 ^1.6.4
^4 ^1.0.3

Installing for older Angular versions

Angular 21 and Ionic with angularx-qrcode 21

npm install angularx-qrcode@21.0.5 --save
# Or with yarn
yarn add angularx-qrcode@21.0.5

Angular 20 and Ionic with angularx-qrcode 20

npm install angularx-qrcode@20.0.0 --save
# Or with yarn
yarn add angularx-qrcode@20.0.0

Angular 19 and Ionic with angularx-qrcode 19

npm install angularx-qrcode@19.0.0 --save
# Or with yarn
yarn add angularx-qrcode@19.0.0

Angular 18 and Ionic with angularx-qrcode 18

npm install angularx-qrcode@18.0.2 --save
# Or with yarn
yarn add angularx-qrcode@18.0.2

Upgrade angularx-qrcode from angularx-qrcode 18 and earlier

Since Angular 19, the latest version of the angularx-qrcode module is now exported as a standalone component. If you’re upgrading from a version before Angular 19, please replace the import statement with the component’s name since it’s now a standalone component.

// OLD - Angular 18 and older
// File: app.module.ts
import { QRCodeModule } from 'angularx-qrcode'

// NEW - Angular 19 and newer
// File: app.component.ts
import { QRCodeComponent } from 'angularx-qrcode'

For more uses with angular 18 and earlier see: angularx/qrcode as ngModule

Security

Report suspected vulnerabilities privately using the security policy. It explains the security-fix policy and what to include in a report.

Repository development and release controls include:

  • GitHub Actions referenced by full commit SHA.
  • CI and release dependency installation with npm ci --ignore-scripts, disabling dependency lifecycle scripts.
  • Repository-local .npmrc settings: ignore-scripts=true, save-exact=true, and min-release-age=7. The release-age setting requires a compatible npm version; see the hardening guide.
  • Read-only checks available through npm run security:ioc and npm run security:cache.

These controls apply to this repository's development, build, and release process. Installing angularx-qrcode does not apply this repository's .npmrc settings to a downstream application. For implementation details and limitations, see npm supply-chain hardening and GitHub Actions cache-poisoning guidance. These guides cover build practices, separately from private vulnerability reporting. Published package provenance is version-specific: it was verified for angularx-qrcode@22.0.1. The npm supply-chain hardening guide explains how to verify a package's provenance and what the attestation establishes.

Contribute

Maintainers: use the curated release-note template and instructions for both major and patch releases.

Install development dependencies with npm ci --ignore-scripts. Run npm start for the Angular development server, or build with npm run build:demo and preview the built application with npm run start:server at http://localhost:3000. The preview uses sirv-cli with SPA fallback and listens on localhost.

The demo uses a small router shell and loads its generator feature lazily, preserving shared URLs and the existing 500 kB initial bundle budget. The generator loads when the root route opens; splitting it improves bootstrap delivery but does not reduce the total JavaScript needed for that page. The upstream qrcode package currently ships CommonJS, so Angular still reports its CommonJS optimization warning; the warning is not suppressed.

  • Please open your PR against the development branch.
  • Make sure your editor uses prettier to minimize commited code changes.
  • You cannot contribute but want to support development? Consider a sponsorship.

Sponsoring

Support the development of angularx-qrcode (or even see your logo here?), consider sponsoring angularx-qrcode. Your support is much appreciated!

License

MIT License

Copyright (c) 2018 - present Andreas Jacob (Cordobo.com)

Releases

Sponsor this project

Packages

Used by

Contributors

Languages