From 6a192603d08a259644690ef17f0e807d8256c5e2 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 10 Sep 2026 19:10:29 +0200 Subject: [PATCH] Port #1221 to dtq-dev-9-base: UFAL/Resolve duplicate HTML element IDs across pages Card X-02a, part A of three. The v9 upgrade took these three templates wholesale from vanilla 9.3, so the fork's hunks from 6628aaf493 were never applied and the pages emit duplicate DOM ids again. ds-select renders one dropdown per sort option on a browse toolbar and one per pool task on /mydspace, but hardcoded its three ids (dsSelectMenuLabel, dsSelectMenuButton, dsSelectDropdownMenu). Every instance after the first therefore duplicated them, and each instance's aria-describedby / aria-labelledby resolved to the *first* instance's elements - a screen reader announced the wrong label for every dropdown but one. A module-level counter now gives each instance a uniqueId and the three ids are suffixed with it. Two adaptations beyond the source hunk, both because 9-base is not 7.x here: * aria-describedby is bound as [attr.aria-describedby]="label ? 'dsSelectMenuLabel-' + uniqueId : null" rather than left hardcoded. The label span is inside @if (label), so without the null branch the button points at an element that does not exist whenever no label is set - a dangling aria reference. The source commit made the same choice; it is restated here because 9-base uses @if where 7.x used *ngIf. * the pool-task row id is id="actions-{{ dso?.id }}" as in the source. Tests added (the source commit ships none): a host rendering two ds-select instances asserts that the document has no duplicate ids, that each button's aria-describedby resolves to a label inside its own instance and to nothing else, and that the two button ids differ; a third case asserts aria-describedby is null when no label is set; and the pool-task spec asserts the actions id is row-specific rather than the constant "actions". Each was proven load-bearing with a negative control - see the PR description. Source: 6628aaf493 (dtq-dev PR #1221) Co-Authored-By: Claude Opus 5 (1M context) --- .../shared/ds-select/ds-select.component.html | 10 +-- .../ds-select/ds-select.component.spec.ts | 69 +++++++++++++++++++ .../shared/ds-select/ds-select.component.ts | 9 +++ ...-search-result-list-element.component.html | 2 +- ...arch-result-list-element.component.spec.ts | 11 ++- 5 files changed, 94 insertions(+), 7 deletions(-) diff --git a/src/app/shared/ds-select/ds-select.component.html b/src/app/shared/ds-select/ds-select.component.html index c5fa369ceb5..8748fa28d9f 100644 --- a/src/app/shared/ds-select/ds-select.component.html +++ b/src/app/shared/ds-select/ds-select.component.html @@ -3,13 +3,13 @@
@if (label) { - + {{ label | translate }} } -