From 55a7b72fd081d6f718069f547b08fde56eba4d28 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 3 Jul 2026 15:05:00 +0200 Subject: [PATCH] fix(aria/listbox): allow navigation to specific index Currently users are only able to programmatically focus the first option in a listbox which may not be enough for some cases. These changes add a `gotoIndex` method that should be a bit more flexible. Fixes #33483. --- goldens/aria/listbox/index.api.md | 1 + src/aria/listbox/listbox.ts | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/goldens/aria/listbox/index.api.md b/goldens/aria/listbox/index.api.md index c851b04d170e..54232cffaefe 100644 --- a/goldens/aria/listbox/index.api.md +++ b/goldens/aria/listbox/index.api.md @@ -19,6 +19,7 @@ export class Listbox implements OnDestroy { readonly element: HTMLElement; readonly focusMode: _angular_core.InputSignal<"roving" | "activedescendant">; gotoFirst(): void; + gotoIndex(index: number): void; readonly id: _angular_core.InputSignal; readonly multi: _angular_core.InputSignalWithTransform; // (undocumented) diff --git a/src/aria/listbox/listbox.ts b/src/aria/listbox/listbox.ts index 616154b6021e..2ac44999361d 100644 --- a/src/aria/listbox/listbox.ts +++ b/src/aria/listbox/listbox.ts @@ -136,16 +136,15 @@ export class Listbox implements OnDestroy { /** The ID of the active descendant in the listbox. */ readonly activeDescendant: Signal; - constructor() { - // Map directives to their patterns for the ListboxPattern - const orderedItemPatterns = computed(() => - this._collection.orderedItems().map(option => option._pattern), - ); + private readonly _orderedItemPatterns = computed(() => + this._collection.orderedItems().map(option => option._pattern), + ); + constructor() { const inputs = { ...this, id: this.id, - items: orderedItemPatterns, + items: this._orderedItemPatterns, activeItem: signal(undefined), textDirection: this.textDirection, element: () => this._elementRef.nativeElement, @@ -210,4 +209,14 @@ export class Listbox implements OnDestroy { gotoFirst() { this._pattern.listBehavior.first(); } + + /** Navigates to an item at a specific index in the listbox. */ + gotoIndex(index: number) { + const patterns = this._orderedItemPatterns(); + const item = patterns[Math.min(Math.max(index, 0), patterns.length - 1)]; + + if (item) { + this._pattern.listBehavior.goto(item); + } + } }