From 9be36703f305de215a331793099abae982408419 Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Thu, 13 Nov 2025 06:22:44 -0700 Subject: [PATCH] fix(multiple): allow ids to be inputs --- src/aria/accordion/accordion.ts | 6 +++--- src/aria/grid/grid.ts | 2 +- src/aria/listbox/listbox.ts | 12 ++---------- src/aria/menu/menu.ts | 4 ++-- src/aria/tabs/tabs.ts | 6 ++---- src/aria/toolbar/toolbar.ts | 5 +---- src/aria/tree/tree.ts | 4 ++-- 7 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/aria/accordion/accordion.ts b/src/aria/accordion/accordion.ts index 3249e05bee9d..4dc259764156 100644 --- a/src/aria/accordion/accordion.ts +++ b/src/aria/accordion/accordion.ts @@ -71,7 +71,7 @@ export class AccordionPanel { private readonly _deferredContentAware = inject(DeferredContentAware); /** A global unique identifier for the panel. */ - private readonly _id = inject(_IdGenerator).getId('accordion-trigger-', true); + readonly id = input(inject(_IdGenerator).getId('ng-accordion-panel-', true)); /** A local unique identifier for the panel, used to match with its trigger's `panelId`. */ readonly panelId = input.required(); @@ -85,7 +85,7 @@ export class AccordionPanel { /** The UI pattern instance for this panel. */ readonly _pattern: AccordionPanelPattern = new AccordionPanelPattern({ - id: () => this._id, + id: this.id, panelId: this.panelId, accordionTrigger: () => this.accordionTrigger(), }); @@ -153,7 +153,7 @@ export class AccordionTrigger { private readonly _accordionGroup = inject(AccordionGroup); /** A unique identifier for the widget. */ - readonly id = input(inject(_IdGenerator).getId('ng-accordion-trigger-', true)); + readonly id = input(inject(_IdGenerator).getId('ng-accordion-trigger-', true)); /** The host native element. */ readonly element = computed(() => this._elementRef.nativeElement); diff --git a/src/aria/grid/grid.ts b/src/aria/grid/grid.ts index 7f9f536bb553..f365396002be 100644 --- a/src/aria/grid/grid.ts +++ b/src/aria/grid/grid.ts @@ -376,7 +376,7 @@ export class GridCellWidget { readonly element = computed(() => this._elementRef.nativeElement); /** A unique identifier for the widget. */ - readonly id = input(inject(_IdGenerator).getId('ng-grid-cell-', true)); + readonly id = input(inject(_IdGenerator).getId('ng-grid-cell-widget-', true)); /** The type of widget, which determines how it is activated. */ readonly widgetType = input<'simple' | 'complex' | 'editable'>('simple'); diff --git a/src/aria/listbox/listbox.ts b/src/aria/listbox/listbox.ts index 01c70723569f..c1df49f5daf0 100644 --- a/src/aria/listbox/listbox.ts +++ b/src/aria/listbox/listbox.ts @@ -65,11 +65,7 @@ import {ComboboxPopup} from '../combobox'; }) export class Listbox { /** A unique identifier for the listbox. */ - private readonly _generatedId = inject(_IdGenerator).getId('ng-listbox-', true); - - // TODO(wagnermaciel): https://github.com/angular/components/pull/30495#discussion_r1972601144. - /** A unique identifier for the listbox. */ - protected id = computed(() => this._generatedId); + readonly id = input(inject(_IdGenerator).getId('ng-listbox-', true)); /** A reference to the parent combobox popup, if one exists. */ private readonly _popup = inject>(ComboboxPopup, { @@ -246,11 +242,7 @@ export class Option { private readonly _listbox = inject(Listbox); /** A unique identifier for the option. */ - private readonly _generatedId = inject(_IdGenerator).getId('ng-option-', true); - - // TODO(wagnermaciel): https://github.com/angular/components/pull/30495#discussion_r1972601144. - /** A unique identifier for the option. */ - protected id = computed(() => this._generatedId); + readonly id = input(inject(_IdGenerator).getId('ng-option-', true)); // TODO(wagnermaciel): See if we want to change how we handle this since textContent is not // reactive. See https://github.com/angular/components/pull/30495#discussion_r1961260216. diff --git a/src/aria/menu/menu.ts b/src/aria/menu/menu.ts index e5e78c79f14b..5b01cb225aa3 100644 --- a/src/aria/menu/menu.ts +++ b/src/aria/menu/menu.ts @@ -187,7 +187,7 @@ export class Menu { readonly textDirection = inject(Directionality).valueSignal; /** The unique ID of the menu. */ - readonly id = input(inject(_IdGenerator).getId('ng-menu-', true)); + readonly id = input(inject(_IdGenerator).getId('ng-menu-', true)); /** Whether the menu should wrap its items. */ readonly wrap = input(true, {transform: booleanAttribute}); @@ -423,7 +423,7 @@ export class MenuItem { readonly element: HTMLElement = this._elementRef.nativeElement; /** The unique ID of the menu item. */ - readonly id = input(inject(_IdGenerator).getId('ng-menu-item-', true)); + readonly id = input(inject(_IdGenerator).getId('ng-menu-item-', true)); /** The value of the menu item. */ readonly value = input.required(); diff --git a/src/aria/tabs/tabs.ts b/src/aria/tabs/tabs.ts index cc2808873175..a69ce363b97a 100644 --- a/src/aria/tabs/tabs.ts +++ b/src/aria/tabs/tabs.ts @@ -298,7 +298,7 @@ export class Tab implements HasElement, OnInit, OnDestroy { private readonly _tabList = inject(TabList); /** A unique identifier for the widget. */ - readonly id = input(inject(_IdGenerator).getId('ng-tab-', true)); + readonly id = input(inject(_IdGenerator).getId('ng-tab-', true)); /** The host native element. */ readonly element = computed(() => this._elementRef.nativeElement); @@ -388,7 +388,7 @@ export class TabPanel implements OnInit, OnDestroy { private readonly _Tabs = inject(Tabs); /** A global unique identifier for the tab. */ - private readonly _id = inject(_IdGenerator).getId('ng-tabpanel-', true); + readonly id = input(inject(_IdGenerator).getId('ng-tabpanel-', true)); /** The Tab UIPattern associated with the tabpanel */ readonly tab = computed(() => @@ -404,8 +404,6 @@ export class TabPanel implements OnInit, OnDestroy { /** The TabPanel UIPattern. */ readonly _pattern: TabPanelPattern = new TabPanelPattern({ ...this, - id: () => this._id, - tab: this.tab, }); constructor() { diff --git a/src/aria/toolbar/toolbar.ts b/src/aria/toolbar/toolbar.ts index 600cc6281600..4f421d4678f8 100644 --- a/src/aria/toolbar/toolbar.ts +++ b/src/aria/toolbar/toolbar.ts @@ -198,10 +198,7 @@ export class ToolbarWidget implements OnInit, OnDestroy { private readonly _toolbar = inject(Toolbar); /** A unique identifier for the widget. */ - private readonly _generatedId = inject(_IdGenerator).getId('ng-toolbar-widget-', true); - - /** A unique identifier for the widget. */ - readonly id = input(this._generatedId); + readonly id = input(inject(_IdGenerator).getId('ng-toolbar-widget-', true)); /** The parent Toolbar UIPattern. */ readonly toolbar = computed(() => this._toolbar._pattern); diff --git a/src/aria/tree/tree.ts b/src/aria/tree/tree.ts index 3079a6c254d2..0afad4d6727e 100644 --- a/src/aria/tree/tree.ts +++ b/src/aria/tree/tree.ts @@ -111,7 +111,7 @@ export class Tree { private readonly _unorderedItems = signal(new Set>()); /** A unique identifier for the tree. */ - readonly id = input(inject(_IdGenerator).getId('ng-tree-', true)); + readonly id = input(inject(_IdGenerator).getId('ng-tree-', true)); /** The host native element. */ readonly element = computed(() => this._elementRef.nativeElement); @@ -278,7 +278,7 @@ export class TreeItem extends DeferredContentAware implements OnInit, OnDestr private readonly _group = signal | undefined>(undefined); /** A unique identifier for the tree item. */ - readonly id = input(inject(_IdGenerator).getId('ng-tree-item-', true)); + readonly id = input(inject(_IdGenerator).getId('ng-tree-item-', true)); /** The host native element. */ readonly element = computed(() => this._elementRef.nativeElement);