88
99import { addAriaReferencedId , removeAriaReferencedId } from '@angular/cdk/a11y' ;
1010import {
11+ afterNextRender ,
1112 AfterViewInit ,
1213 booleanAttribute ,
1314 ChangeDetectorRef ,
@@ -18,6 +19,7 @@ import {
1819 inject ,
1920 Inject ,
2021 InjectionToken ,
22+ Injector ,
2123 Input ,
2224 NgZone ,
2325 OnChanges ,
@@ -227,6 +229,10 @@ export class MatAutocompleteTrigger
227229 @Input ( { alias : 'matAutocompleteDisabled' , transform : booleanAttribute } )
228230 autocompleteDisabled : boolean ;
229231
232+ private _initialized = new Subject ( ) ;
233+
234+ private _injector = inject ( Injector ) ;
235+
230236 constructor (
231237 private _element : ElementRef < HTMLInputElement > ,
232238 private _overlay : Overlay ,
@@ -249,6 +255,9 @@ export class MatAutocompleteTrigger
249255 private _aboveClass = 'mat-mdc-autocomplete-panel-above' ;
250256
251257 ngAfterViewInit ( ) {
258+ this . _initialized . next ( ) ;
259+ this . _initialized . complete ( ) ;
260+
252261 const window = this . _getWindow ( ) ;
253262
254263 if ( typeof window !== 'undefined' ) {
@@ -301,8 +310,8 @@ export class MatAutocompleteTrigger
301310
302311 if ( this . panelOpen ) {
303312 // Only emit if the panel was visible.
304- // The `NgZone.onStable ` always emits outside of the Angular zone,
305- // so all the subscriptions from `_subscribeToClosingActions()` are also outside of the Angular zone.
313+ // `afterNextRender ` always runs outside of the Angular zone, so all the subscriptions from
314+ // `_subscribeToClosingActions()` are also outside of the Angular zone.
306315 // We should manually run in Angular zone to update UI after panel closing.
307316 this . _zone . run ( ( ) => {
308317 this . autocomplete . closed . emit ( ) ;
@@ -378,10 +387,7 @@ export class MatAutocompleteTrigger
378387
379388 // If there are any subscribers before `ngAfterViewInit`, the `autocomplete` will be undefined.
380389 // Return a stream that we'll replace with the real one once everything is in place.
381- return this . _zone . onStable . pipe (
382- take ( 1 ) ,
383- switchMap ( ( ) => this . optionSelections ) ,
384- ) ;
390+ return this . _initialized . pipe ( switchMap ( ( ) => this . optionSelections ) ) ;
385391 } ) as Observable < MatOptionSelectionChange > ;
386392
387393 /** The currently active option, coerced to MatOption type. */
@@ -592,25 +598,32 @@ export class MatAutocompleteTrigger
592598 * stream every time the option list changes.
593599 */
594600 private _subscribeToClosingActions ( ) : Subscription {
595- const firstStable = this . _zone . onStable . pipe ( take ( 1 ) ) ;
601+ const initialRender = new Observable ( subscriber => {
602+ afterNextRender (
603+ ( ) => {
604+ subscriber . next ( ) ;
605+ } ,
606+ { injector : this . _injector } ,
607+ ) ;
608+ } ) ;
596609 const optionChanges = this . autocomplete . options . changes . pipe (
597610 tap ( ( ) => this . _positionStrategy . reapplyLastPosition ( ) ) ,
598611 // Defer emitting to the stream until the next tick, because changing
599612 // bindings in here will cause "changed after checked" errors.
600613 delay ( 0 ) ,
601614 ) ;
602615
603- // When the zone is stable initially, and when the option list changes...
616+ // When the options are initially rendered , and when the option list changes...
604617 return (
605- merge ( firstStable , optionChanges )
618+ merge ( initialRender , optionChanges )
606619 . pipe (
607620 // create a new stream of panelClosingActions, replacing any previous streams
608621 // that were created, and flatten it so our stream only emits closing events...
609- switchMap ( ( ) => {
610- // The `NgZone.onStable` always emits outside of the Angular zone, thus we have to re-enter
611- // the Angular zone. This will lead to change detection being called outside of the Angular
612- // zone and the `autocomplete.opened` will also emit outside of the Angular.
622+ switchMap ( ( ) =>
613623 this . _zone . run ( ( ) => {
624+ // `afterNextRender` always runs outside of the Angular zone, thus we have to re-enter
625+ // the Angular zone. This will lead to change detection being called outside of the Angular
626+ // zone and the `autocomplete.opened` will also emit outside of the Angular.
614627 const wasOpen = this . panelOpen ;
615628 this . _resetActiveItem ( ) ;
616629 this . _updatePanelState ( ) ;
@@ -634,10 +647,10 @@ export class MatAutocompleteTrigger
634647 this . autocomplete . closed . emit ( ) ;
635648 }
636649 }
637- } ) ;
638650
639- return this . panelClosingActions ;
640- } ) ,
651+ return this . panelClosingActions ;
652+ } ) ,
653+ ) ,
641654 // when the first closing event occurs...
642655 take ( 1 ) ,
643656 )
0 commit comments