Is this a regression?
The previous version in which this bug was not present was
No response
Description
Setting the combobox's expanded model to true programmatically (e.g. open-on-focus) does not keep the popup open under Zone.js change detection: expanded is immediately reset to
false, so the popup never becomes visible. The same code works correctly under provideZonelessChangeDetection().
Keyboard-driven opening (ArrowDown) works fine under Zone.js — only programmatically setting expanded fails.
This looks like the same class of Zone.js afterRenderEffect scheduling issue fixed for the keyboard relay in #33453 (commit e87216c), but applied only to keyboardEventRelayEffect. In
src/aria/combobox/combobox.ts the sibling effects are still registered in the default phase:
afterRenderEffect({ write: () => this._pattern.keyboardEventRelayEffect() }); // fixed in #33453 (https://github.com/angular/components/pull/33453)
afterRenderEffect(() => this._pattern.closePopupOnBlurEffect()); // still default phase
afterRenderEffect(() => { this.contentVisible.set(this._pattern.isExpanded()); }); // still default phase
closePopupOnBlurEffect() does:
if (expanded && !alwaysExpanded && !comboboxFocused && !popupFocused) {
this.inputs.expanded.set(false);
}
Under Zone.js, when expanded is set in a focus handler, this effect observes isFocused() as still false and resets expanded. alwaysExpanded is the only way to keep the popup
open, but it permanently forces isExpanded() true, disabling Escape-to-close and ArrowUp/Down-to-open.
Reproduction
StackBlitz link: https://stackblitz.com/edit/components-issue-starter-vhdrsdal?file=src%2Fmain.ts
Steps to reproduce:
Minimal editable combobox, bootstrapped with provideZoneChangeDetection():
<input ngCombobox #cb="ngCombobox" [(expanded)]="expanded" (focus)="expanded.set(true)" />
<ng-template ngComboboxPopup [combobox]="cb">
<div ngListbox ngComboboxWidget>
<div ngOption value="a">A</div>
</div>
</ng-template>
- Focus the input.
- Popup briefly opens then closes;
expanded reads false in devtools.
- Switch to
provideZonelessChangeDetection() → works as expected.
Expected
Setting expanded = true (while the input is focused) keeps the popup open under Zone.js, matching zoneless behaviour.
Actual
expanded is reset to false by closePopupOnBlurEffect before the focus state settles; popup does not stay open.
Expected Behavior
Setting expanded = true (while the input is focused) keeps the popup open under Zone.js, matching zoneless behaviour.
Actual Behavior
expanded is reset to false by closePopupOnBlurEffect before the focus state settles; popup does not stay open.
Environment
@angular/aria, @angular/cdk, @angular/core: 22.0.3
- Zone.js: enabled (
provideZoneChangeDetection())
- Repro also expected on
main (effects still default-phase).
Is this a regression?
The previous version in which this bug was not present was
No response
Description
Setting the combobox's
expandedmodel totrueprogrammatically (e.g. open-on-focus) does not keep the popup open under Zone.js change detection:expandedis immediately reset tofalse, so the popup never becomes visible. The same code works correctly underprovideZonelessChangeDetection().Keyboard-driven opening (
ArrowDown) works fine under Zone.js — only programmatically settingexpandedfails.This looks like the same class of Zone.js
afterRenderEffectscheduling issue fixed for the keyboard relay in #33453 (commit e87216c), but applied only tokeyboardEventRelayEffect. Insrc/aria/combobox/combobox.tsthe sibling effects are still registered in the default phase:closePopupOnBlurEffect()does:Under Zone.js, when
expandedis set in afocushandler, this effect observesisFocused()as stillfalseand resetsexpanded.alwaysExpandedis the only way to keep the popupopen, but it permanently forces
isExpanded()true, disablingEscape-to-close andArrowUp/Down-to-open.Reproduction
StackBlitz link: https://stackblitz.com/edit/components-issue-starter-vhdrsdal?file=src%2Fmain.ts
Steps to reproduce:
Minimal editable combobox, bootstrapped with
provideZoneChangeDetection():expandedreadsfalsein devtools.provideZonelessChangeDetection()→ works as expected.Expected
Setting
expanded = true(while the input is focused) keeps the popup open under Zone.js, matching zoneless behaviour.Actual
expandedis reset tofalsebyclosePopupOnBlurEffectbefore the focus state settles; popup does not stay open.Expected Behavior
Setting
expanded = true(while the input is focused) keeps the popup open under Zone.js, matching zoneless behaviour.Actual Behavior
expandedis reset tofalsebyclosePopupOnBlurEffectbefore the focus state settles; popup does not stay open.Environment
@angular/aria,@angular/cdk,@angular/core: 22.0.3provideZoneChangeDetection())main(effects still default-phase).