Skip to content

fix(aria/combobox): empty aria-controls when the popup widget has no id - #33635

Open
lazerg wants to merge 3 commits into
angular:mainfrom
lazerg:fix/issue-70082-combobox-empty-aria-controls
Open

fix(aria/combobox): empty aria-controls when the popup widget has no id#33635
lazerg wants to merge 3 commits into
angular:mainfrom
lazerg:fix/issue-70082-combobox-empty-aria-controls

Conversation

@lazerg

@lazerg lazerg commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

ngComboboxWidget reads its ID off the host element, so a popup whose widget doesn't set one (for example the dialog popup in the docs, where the widget is a plain div) leaves the combobox with aria-controls="", which Axe flags. The same happened when the ID came from a host binding such as ngListbox, since it isn't on the element yet when the widget reads it.

The widget now generates an ID after the first render if the element still doesn't have one, and re-reads the ID at that point so binding-provided ones are picked up.

Fixes #33640.

@pullapprove
pullapprove Bot requested review from andrewseguin and tjshiu August 5, 2026 08:14
@angular-robot angular-robot Bot added area: aria/combobox area: docs Related to the documentation labels Aug 5, 2026
@lazerg
lazerg force-pushed the fix/issue-70082-combobox-empty-aria-controls branch from 1cef0e3 to 70a1084 Compare August 5, 2026 08:32
@crisbeto
crisbeto requested a review from ok7sai August 5, 2026 20:01

@ok7sai ok7sai left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! Overall looks good.

Comment thread src/aria/combobox/combobox.spec.ts Outdated
});
});

describe('with Dialog', () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest restructure the test group to something like

describe('ComboboxWidget', () => {
  it('should auto-generate an ID on widget when none is provided', async () => {
    // Tests plain widget without id -> receives 'ng-combobox-widget-X'
  });
  it('should preserve an explicit ID on the widget element', async () => {
    // Tests <div ngComboboxWidget id="custom-id"> -> uses 'custom-id'
  });
  it('should prioritize sibling directive IDs over generated IDs', async () => {
    // Tests <div ngComboboxWidget ngListbox> -> uses 'ng-listbox-X'
  });
});

For better describing the wanted behaviors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in da624a1. Two of the three fail on main; the explicit-id one passes there and guards against a regression.

@ok7sai ok7sai added action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release labels Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: merge The PR is ready for merge by the caretaker area: aria/combobox area: docs Related to the documentation target: patch This PR is targeted for the next patch release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Combobox sets an empty aria-controls attribute when using a dialog popup

2 participants