From ec705bf7e32d41418b4ab7346bee6879f7ec4556 Mon Sep 17 00:00:00 2001 From: Ali Toghiani Date: Tue, 19 Aug 2025 19:38:26 +0330 Subject: [PATCH 1/4] ref(angularx-qrcode.component.ts): prevent qr regeneration on accessibility input changes --- .../src/lib/angularx-qrcode.component.ts | 100 +++++++++++++----- 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts index 5d946e0..5c25c45 100644 --- a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts +++ b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts @@ -8,6 +8,7 @@ import { Output, Renderer2, ViewChild, + SimpleChanges, } from "@angular/core" import { DomSanitizer, SafeUrl } from "@angular/platform-browser" import { @@ -65,8 +66,77 @@ export class QRCodeComponent implements OnChanges { private sanitizer: DomSanitizer ) {} - public async ngOnChanges(): Promise { - await this.createQRCode() + public async ngOnChanges(changes: SimpleChanges): Promise { + if (this.hasVisualChanges(changes)) { + await this.createQRCode() // Regenerate QR code + } + + if (this.hasAccessibilityChanges(changes)) { + this.setAccessibilityAttributes() // Update existing element attributes + } + } + + private hasVisualChanges(changes: SimpleChanges): boolean { + // Core inputs that affect QR generation for all element types + const universalVisualInputs = new Set([ + "qrdata", + "colorDark", + "colorLight", + "errorCorrectionLevel", + "margin", + "scale", + "version", + "width", + "allowEmptyString", + ]) + + // Element type change always requires regeneration + if (changes["elementType"]) { + return true + } + + // Image-related inputs only matter for canvas element type + const imageInputs = new Set(["imageSrc", "imageHeight", "imageWidth"]) + const hasImageChanges = Object.keys(changes).some((key) => + imageInputs.has(key) + ) + + if (hasImageChanges && this.elementType === "canvas") { + return true + } + + // Check if any universal visual inputs changed + return Object.keys(changes).some((key) => universalVisualInputs.has(key)) + } + + private hasAccessibilityChanges(changes: SimpleChanges): boolean { + const accessibilityInputs = new Set(["alt", "ariaLabel", "title"]) + + return Object.keys(changes).some((key) => accessibilityInputs.has(key)) + } + + private setAccessibilityAttributes(el?: HTMLElement | SVGSVGElement): void { + const qrElement = el || this.qrcElement.nativeElement.firstChild as + | HTMLElement + | SVGSVGElement + + if (!qrElement) { + return + } + + const tag = qrElement.tagName.toLowerCase() + + if (this.ariaLabel) { + this.renderer.setAttribute(qrElement, "aria-label", this.ariaLabel) + } + + if (this.title) { + this.renderer.setAttribute(qrElement, "title", this.title) + } + + if (this.alt && tag === "img") { + this.renderer.setAttribute(qrElement, "alt", this.alt) + } } protected isValidQrCodeText(data: string | null): boolean { @@ -205,20 +275,7 @@ export class QRCodeComponent implements OnChanges { this.context = canvasElement.getContext("2d") this.toCanvas(canvasElement, config) .then(() => { - if (this.ariaLabel) { - this.renderer.setAttribute( - canvasElement, - "aria-label", - `${this.ariaLabel}` - ) - } - if (this.title) { - this.renderer.setAttribute( - canvasElement, - "title", - `${this.title}` - ) - } + this.setAccessibilityAttributes(canvasElement) if (centerImageSrc && this.context) { this.centerImage = new Image( @@ -277,6 +334,7 @@ export class QRCodeComponent implements OnChanges { this.renderer.setAttribute(svgElement, "width", `${this.width}`) this.renderElement(svgElement) this.emitQRCodeURL(svgElement) + this.setAccessibilityAttributes(svgElement) }) .catch((e) => { console.error("[angularx-qrcode] svg error:", e) @@ -290,18 +348,10 @@ export class QRCodeComponent implements OnChanges { this.renderer.createElement("img") this.toDataURL(config) .then((dataUrl: string) => { - if (this.alt) { - imgElement.setAttribute("alt", this.alt) - } - if (this.ariaLabel) { - imgElement.setAttribute("aria-label", this.ariaLabel) - } imgElement.setAttribute("src", dataUrl) - if (this.title) { - imgElement.setAttribute("title", this.title) - } this.renderElement(imgElement) this.emitQRCodeURL(imgElement) + this.setAccessibilityAttributes(imgElement) }) .catch((e) => { console.error("[angularx-qrcode] img/url error:", e) From 0740f674b5cb69d61dc30670f242ca3b74be9b7e Mon Sep 17 00:00:00 2001 From: Ali Toghiani <60219120+ali-toghiani@users.noreply.github.com> Date: Wed, 20 Aug 2025 23:58:04 +0330 Subject: [PATCH 2/4] Update projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts index 5c25c45..258baca 100644 --- a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts +++ b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts @@ -119,7 +119,8 @@ export class QRCodeComponent implements OnChanges { const qrElement = el || this.qrcElement.nativeElement.firstChild as | HTMLElement | SVGSVGElement - + const qrElement = (el || this.qrcElement.nativeElement.firstChild) as + HTMLElement | SVGSVGElement if (!qrElement) { return } From 96d50b9ea3835840c3586e9c215a856830084002 Mon Sep 17 00:00:00 2001 From: Ali Toghiani <60219120+ali-toghiani@users.noreply.github.com> Date: Wed, 20 Aug 2025 23:58:23 +0330 Subject: [PATCH 3/4] Update projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts index 258baca..3704df1 100644 --- a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts +++ b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts @@ -68,7 +68,7 @@ export class QRCodeComponent implements OnChanges { public async ngOnChanges(changes: SimpleChanges): Promise { if (this.hasVisualChanges(changes)) { - await this.createQRCode() // Regenerate QR code + await this.createQRCode() } if (this.hasAccessibilityChanges(changes)) { From e97a482e1c1b33a99cb51aac5572a6e3f615c40a Mon Sep 17 00:00:00 2001 From: Ali Toghiani <60219120+ali-toghiani@users.noreply.github.com> Date: Wed, 20 Aug 2025 23:58:37 +0330 Subject: [PATCH 4/4] Update projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts index 3704df1..bae8a62 100644 --- a/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts +++ b/projects/angularx-qrcode/src/lib/angularx-qrcode.component.ts @@ -72,7 +72,7 @@ export class QRCodeComponent implements OnChanges { } if (this.hasAccessibilityChanges(changes)) { - this.setAccessibilityAttributes() // Update existing element attributes + this.setAccessibilityAttributes() } }