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.
- Demo App
- Installation
- Build a minimal Angular app
- Usage & Example Implementations
- Available Parameters
- Compatibility and maintenance
- Security
- Contribute
- Sponsoring
- License
Different QR Code styles: regular, with image/logo, custom colors. Generate your own QR Code here: angular qr code web 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 startOpen 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:serverOpen http://localhost:3000/. Restart the preview server after rebuilding so it serves the updated files.
Angular 22 and Ionic with angularx-qrcode 22
# npm
npm install angularx-qrcode
# yarn
yarn add angularx-qrcode
# pnpm
pnpm add angularx-qrcodeFor an existing Angular 22 application, continue with the integration examples. For an older Angular major, use the version mapping and installation commands below.
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.
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.
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-qrcodeReplace 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 startOpen 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.
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.
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.
}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" />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')
}
}The online demo includes a working download example.
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.
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.
(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.
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>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.
- 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
qrCodeURLare lifecycle-managed and revoked on replacement/component destroy.
- 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)
| 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) |
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.
- Payload size and dimensions: Keep
qrdataas short as your use case allows. More data generally needs a more complex QR code and may require a larger renderedwidthso scanners can distinguish its modules. Leaveversionautomatic 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
marginoption controls this quiet zone in modules and defaults to4. Avoid cropping the border or covering it with neighboring content in your page or print layout. - Error correction:
errorCorrectionLevelacceptsL,M,Q, andH(defaultM). 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, andimageHeight; keep the overlay small, consider higher error correction such asQorH, 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:
qrdatais 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.
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.
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:ssrThis 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.
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 |
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.5Angular 20 and Ionic with angularx-qrcode 20
npm install angularx-qrcode@20.0.0 --save
# Or with yarn
yarn add angularx-qrcode@20.0.0Angular 19 and Ionic with angularx-qrcode 19
npm install angularx-qrcode@19.0.0 --save
# Or with yarn
yarn add angularx-qrcode@19.0.0Angular 18 and Ionic with angularx-qrcode 18
npm install angularx-qrcode@18.0.2 --save
# Or with yarn
yarn add angularx-qrcode@18.0.2Since 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
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
.npmrcsettings:ignore-scripts=true,save-exact=true, andmin-release-age=7. The release-age setting requires a compatible npm version; see the hardening guide. - Read-only checks available through
npm run security:iocandnpm 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.
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.
Support the development of angularx-qrcode (or even see your logo here?), consider sponsoring angularx-qrcode. Your support is much appreciated!
MIT License
Copyright (c) 2018 - present Andreas Jacob (Cordobo.com)
