Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion goldens/cdk/a11y/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export interface Highlightable extends ListKeyManagerOption {

// @public
export class _IdGenerator {
getId(prefix: string): string;
getId(prefix: string, randomize?: boolean): string;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<_IdGenerator, never>;
// (undocumented)
Expand Down
4 changes: 2 additions & 2 deletions src/aria/accordion/accordion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class AccordionPanel {
private readonly _deferredContentAware = inject(DeferredContentAware);

/** A global unique identifier for the panel. */
private readonly _id = inject(_IdGenerator).getId('accordion-trigger-');
private readonly _id = inject(_IdGenerator).getId('accordion-trigger-', true);

/** A local unique identifier for the panel, used to match with its trigger's value. */
value = input.required<string>();
Expand Down Expand Up @@ -102,7 +102,7 @@ export class AccordionPanel {
})
export class AccordionTrigger {
/** A global unique identifier for the trigger. */
private readonly _id = inject(_IdGenerator).getId('ng-accordion-trigger-');
private readonly _id = inject(_IdGenerator).getId('ng-accordion-trigger-', true);

/** A reference to the trigger element. */
private readonly _elementRef = inject(ElementRef);
Expand Down
2 changes: 1 addition & 1 deletion src/aria/grid/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export class GridCell {
private readonly _row = inject(GridRow);

/** A unique identifier for the cell. */
private readonly _id = inject(_IdGenerator).getId('ng-grid-cell-');
private readonly _id = inject(_IdGenerator).getId('ng-grid-cell-', true);

/** The host native element. */
readonly element = computed(() => this._elementRef.nativeElement);
Expand Down
4 changes: 2 additions & 2 deletions src/aria/listbox/listbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ import {ComboboxPopup} from '../combobox';
})
export class Listbox<V> {
/** A unique identifier for the listbox. */
private readonly _generatedId = inject(_IdGenerator).getId('ng-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. */
Expand Down Expand Up @@ -207,7 +207,7 @@ export class Option<V> {
private readonly _listbox = inject(Listbox);

/** A unique identifier for the option. */
private readonly _generatedId = inject(_IdGenerator).getId('ng-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. */
Expand Down
5 changes: 3 additions & 2 deletions src/aria/menu/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
MenuPattern,
MenuTriggerPattern,
} from '@angular/aria/private';
import {_IdGenerator} from '@angular/cdk/a11y';
import {toSignal} from '@angular/core/rxjs-interop';
import {Directionality} from '@angular/cdk/bidi';

Expand Down Expand Up @@ -132,7 +133,7 @@ export class Menu<V> {
readonly submenu = input<Menu<V> | undefined>(undefined);

/** The unique ID of the menu. */
readonly id = input<string>(Math.random().toString(36).substring(2, 10));
readonly id = input<string>(inject(_IdGenerator).getId('ng-menu-', true));

/** Whether the menu should wrap its items. */
readonly wrap = input<boolean>(true);
Expand Down Expand Up @@ -325,7 +326,7 @@ export class MenuItem<V> {
readonly element: HTMLElement = this._elementRef.nativeElement;

/** The unique ID of the menu item. */
readonly id = input<string>(Math.random().toString(36).substring(2, 10));
readonly id = input<string>(inject(_IdGenerator).getId('ng-menu-item-', true));

/** The value of the menu item. */
readonly value = input.required<V>();
Expand Down
2 changes: 1 addition & 1 deletion src/aria/radio-group/radio-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export class RadioButton<V> {
private readonly _radioGroup = inject(RadioGroup);

/** A unique identifier for the radio button. */
private readonly _generatedId = inject(_IdGenerator).getId('ng-radio-button-');
private readonly _generatedId = inject(_IdGenerator).getId('ng-radio-button-', true);

/** A unique identifier for the radio button. */
readonly id = computed(() => this._generatedId);
Expand Down
2 changes: 1 addition & 1 deletion src/aria/tabs/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,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-');
private readonly _id = inject(_IdGenerator).getId('ng-tabpanel-', true);

/** The Tab UIPattern associated with the tabpanel */
readonly tab = computed(() => this._Tabs.tabs()?.find(tab => tab.value() === this.value()));
Expand Down
4 changes: 2 additions & 2 deletions src/aria/toolbar/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export class ToolbarWidget<V> implements OnInit, OnDestroy {
private readonly _toolbar = inject(Toolbar);

/** A unique identifier for the widget. */
private readonly _generatedId = inject(_IdGenerator).getId('ng-toolbar-widget-');
private readonly _generatedId = inject(_IdGenerator).getId('ng-toolbar-widget-', true);

/** A unique identifier for the widget. */
readonly id = computed(() => this._generatedId);
Expand Down Expand Up @@ -236,7 +236,7 @@ export class ToolbarWidgetGroup<V> implements OnInit, OnDestroy {
private readonly _toolbar = inject(Toolbar, {optional: true});

/** A unique identifier for the widget. */
private readonly _generatedId = inject(_IdGenerator).getId('ng-toolbar-widget-group-');
private readonly _generatedId = inject(_IdGenerator).getId('ng-toolbar-widget-group-', true);

/** A unique identifier for the widget. */
readonly id = computed(() => this._generatedId);
Expand Down
4 changes: 2 additions & 2 deletions src/aria/tree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function sortDirectives(a: HasElement, b: HasElement) {
})
export class Tree<V> {
/** A unique identifier for the tree. */
private readonly _generatedId = inject(_IdGenerator).getId('ng-tree-');
private readonly _generatedId = inject(_IdGenerator).getId('ng-tree-', true);

// TODO(wagnermaciel): https://github.com/angular/components/pull/30495#discussion_r1972601144.
/** A unique identifier for the tree. */
Expand Down Expand Up @@ -229,7 +229,7 @@ export class TreeItem<V> extends DeferredContentAware implements OnInit, OnDestr
private readonly _elementRef = inject(ElementRef);

/** A unique identifier for the tree item. */
private readonly _id = inject(_IdGenerator).getId('ng-tree-item-');
private readonly _id = inject(_IdGenerator).getId('ng-tree-item-', true);

/** The owned tree item group. */
private readonly _group = signal<TreeItemGroup<V> | undefined>(undefined);
Expand Down
6 changes: 4 additions & 2 deletions src/cdk/a11y/id-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ const counters: Record<string, number> = {};
@Injectable({providedIn: 'root'})
export class _IdGenerator {
private _appId = inject(APP_ID);
private _infix = `a${Math.floor(Math.random() * 100000).toString()}`;

/**
* Generates a unique ID with a specific prefix.
* @param prefix Prefix to add to the ID.
* @param randomize Add a randomized infix string.
*/
getId(prefix: string): string {
getId(prefix: string, randomize: boolean = false): string {
// Omit the app ID if it's the default `ng`. Since the vast majority of pages have one
// Angular app on them, we can reduce the amount of breakages by not adding it.
if (this._appId !== 'ng') {
Expand All @@ -35,6 +37,6 @@ export class _IdGenerator {
counters[prefix] = 0;
}

return `${prefix}${counters[prefix]++}`;
return `${prefix}${randomize ? this._infix + '-' : ''}${counters[prefix]++}`;
}
}
Loading