8
8
9
9
import { addAriaReferencedId , removeAriaReferencedId } from '@angular/cdk/a11y' ;
10
10
import {
11
+ afterNextRender ,
11
12
AfterViewInit ,
12
13
booleanAttribute ,
13
14
ChangeDetectorRef ,
@@ -18,6 +19,7 @@ import {
18
19
inject ,
19
20
Inject ,
20
21
InjectionToken ,
22
+ Injector ,
21
23
Input ,
22
24
NgZone ,
23
25
OnChanges ,
@@ -227,6 +229,10 @@ export class MatAutocompleteTrigger
227
229
@Input ( { alias : 'matAutocompleteDisabled' , transform : booleanAttribute } )
228
230
autocompleteDisabled : boolean ;
229
231
232
+ private _initialized = new Subject ( ) ;
233
+
234
+ private _injector = inject ( Injector ) ;
235
+
230
236
constructor (
231
237
private _element : ElementRef < HTMLInputElement > ,
232
238
private _overlay : Overlay ,
@@ -249,6 +255,9 @@ export class MatAutocompleteTrigger
249
255
private _aboveClass = 'mat-mdc-autocomplete-panel-above' ;
250
256
251
257
ngAfterViewInit ( ) {
258
+ this . _initialized . next ( ) ;
259
+ this . _initialized . complete ( ) ;
260
+
252
261
const window = this . _getWindow ( ) ;
253
262
254
263
if ( typeof window !== 'undefined' ) {
@@ -301,8 +310,8 @@ export class MatAutocompleteTrigger
301
310
302
311
if ( this . panelOpen ) {
303
312
// 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.
306
315
// We should manually run in Angular zone to update UI after panel closing.
307
316
this . _zone . run ( ( ) => {
308
317
this . autocomplete . closed . emit ( ) ;
@@ -378,10 +387,7 @@ export class MatAutocompleteTrigger
378
387
379
388
// If there are any subscribers before `ngAfterViewInit`, the `autocomplete` will be undefined.
380
389
// 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 ) ) ;
385
391
} ) as Observable < MatOptionSelectionChange > ;
386
392
387
393
/** The currently active option, coerced to MatOption type. */
@@ -592,25 +598,32 @@ export class MatAutocompleteTrigger
592
598
* stream every time the option list changes.
593
599
*/
594
600
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
+ } ) ;
596
609
const optionChanges = this . autocomplete . options . changes . pipe (
597
610
tap ( ( ) => this . _positionStrategy . reapplyLastPosition ( ) ) ,
598
611
// Defer emitting to the stream until the next tick, because changing
599
612
// bindings in here will cause "changed after checked" errors.
600
613
delay ( 0 ) ,
601
614
) ;
602
615
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...
604
617
return (
605
- merge ( firstStable , optionChanges )
618
+ merge ( initialRender , optionChanges )
606
619
. pipe (
607
620
// create a new stream of panelClosingActions, replacing any previous streams
608
621
// 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 ( ( ) =>
613
623
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.
614
627
const wasOpen = this . panelOpen ;
615
628
this . _resetActiveItem ( ) ;
616
629
this . _updatePanelState ( ) ;
@@ -634,10 +647,10 @@ export class MatAutocompleteTrigger
634
647
this . autocomplete . closed . emit ( ) ;
635
648
}
636
649
}
637
- } ) ;
638
650
639
- return this . panelClosingActions ;
640
- } ) ,
651
+ return this . panelClosingActions ;
652
+ } ) ,
653
+ ) ,
641
654
// when the first closing event occurs...
642
655
take ( 1 ) ,
643
656
)
0 commit comments