@@ -19,6 +19,8 @@ import {
19
19
ElementRef ,
20
20
Inject ,
21
21
InjectionToken ,
22
+ Injector ,
23
+ inject ,
22
24
Input ,
23
25
NgZone ,
24
26
OnDestroy ,
@@ -27,6 +29,7 @@ import {
27
29
ViewChild ,
28
30
ViewEncapsulation ,
29
31
ANIMATION_MODULE_TYPE ,
32
+ afterRender ,
30
33
} from '@angular/core' ;
31
34
import { AbstractControlDirective } from '@angular/forms' ;
32
35
import { ThemePalette } from '@angular/material/core' ;
@@ -245,7 +248,7 @@ export class MatFormField
245
248
// If the appearance has been switched to `outline`, the label offset needs to be updated.
246
249
// The update can happen once the view has been re-checked, but not immediately because
247
250
// the view has not been updated and the notched-outline floating label is not present.
248
- this . _needsOutlineLabelOffsetUpdateOnStable = true ;
251
+ this . _needsOutlineLabelOffsetUpdate = true ;
249
252
}
250
253
}
251
254
private _appearance : MatFormFieldAppearance = DEFAULT_APPEARANCE ;
@@ -300,12 +303,18 @@ export class MatFormField
300
303
private _destroyed = new Subject < void > ( ) ;
301
304
private _isFocused : boolean | null = null ;
302
305
private _explicitFormFieldControl : MatFormFieldControl < any > ;
303
- private _needsOutlineLabelOffsetUpdateOnStable = false ;
306
+ private _needsOutlineLabelOffsetUpdate = false ;
307
+
308
+ private _injector = inject ( Injector ) ;
304
309
305
310
constructor (
306
311
public _elementRef : ElementRef ,
307
312
private _changeDetectorRef : ChangeDetectorRef ,
308
- private _ngZone : NgZone ,
313
+ /**
314
+ * @deprecated not needed, to be removed.
315
+ * @breaking -change 19.0.0 remove this param
316
+ */
317
+ _unusedNgZone : NgZone ,
309
318
private _dir : Directionality ,
310
319
private _platform : Platform ,
311
320
@Optional ( )
@@ -485,30 +494,30 @@ export class MatFormField
485
494
* The floating label in the docked state needs to account for prefixes. The horizontal offset
486
495
* is calculated whenever the appearance changes to `outline`, the prefixes change, or when the
487
496
* form field is added to the DOM. This method sets up all subscriptions which are needed to
488
- * trigger the label offset update. In general, we want to avoid performing measurements often,
489
- * so we rely on the `NgZone` as indicator when the offset should be recalculated, instead of
490
- * checking every change detection cycle.
497
+ * trigger the label offset update.
491
498
*/
492
499
private _initializeOutlineLabelOffsetSubscriptions ( ) {
493
500
// Whenever the prefix changes, schedule an update of the label offset.
494
- this . _prefixChildren . changes . subscribe (
495
- ( ) => ( this . _needsOutlineLabelOffsetUpdateOnStable = true ) ,
496
- ) ;
497
-
498
- // Note that we have to run outside of the `NgZone` explicitly, in order to avoid
499
- // throwing users into an infinite loop if `zone-patch-rxjs` is included.
500
- this . _ngZone . runOutsideAngular ( ( ) => {
501
- this . _ngZone . onStable . pipe ( takeUntil ( this . _destroyed ) ) . subscribe ( ( ) => {
502
- if ( this . _needsOutlineLabelOffsetUpdateOnStable ) {
503
- this . _needsOutlineLabelOffsetUpdateOnStable = false ;
501
+ // TODO(mmalerba): Use ResizeObserver to better support dynamically changing prefix content.
502
+ this . _prefixChildren . changes . subscribe ( ( ) => ( this . _needsOutlineLabelOffsetUpdate = true ) ) ;
503
+
504
+ // TODO(mmalerba): Split this into separate `afterRender` calls using the `EarlyRead` and
505
+ // `Write` phases.
506
+ afterRender (
507
+ ( ) => {
508
+ if ( this . _needsOutlineLabelOffsetUpdate ) {
509
+ this . _needsOutlineLabelOffsetUpdate = false ;
504
510
this . _updateOutlineLabelOffset ( ) ;
505
511
}
506
- } ) ;
507
- } ) ;
512
+ } ,
513
+ {
514
+ injector : this . _injector ,
515
+ } ,
516
+ ) ;
508
517
509
518
this . _dir . change
510
519
. pipe ( takeUntil ( this . _destroyed ) )
511
- . subscribe ( ( ) => ( this . _needsOutlineLabelOffsetUpdateOnStable = true ) ) ;
520
+ . subscribe ( ( ) => ( this . _needsOutlineLabelOffsetUpdate = true ) ) ;
512
521
}
513
522
514
523
/** Whether the floating label should always float or not. */
@@ -653,7 +662,7 @@ export class MatFormField
653
662
* incorporate the horizontal offset into their default text-field styles.
654
663
*/
655
664
private _updateOutlineLabelOffset ( ) {
656
- if ( ! this . _platform . isBrowser || ! this . _hasOutline ( ) || ! this . _floatingLabel ) {
665
+ if ( ! this . _hasOutline ( ) || ! this . _floatingLabel ) {
657
666
return ;
658
667
}
659
668
const floatingLabel = this . _floatingLabel . element ;
@@ -666,7 +675,7 @@ export class MatFormField
666
675
// If the form field is not attached to the DOM yet (e.g. in a tab), we defer
667
676
// the label offset update until the zone stabilizes.
668
677
if ( ! this . _isAttachedToDom ( ) ) {
669
- this . _needsOutlineLabelOffsetUpdateOnStable = true ;
678
+ this . _needsOutlineLabelOffsetUpdate = true ;
670
679
return ;
671
680
}
672
681
const iconPrefixContainer = this . _iconPrefixContainer ?. nativeElement ;
0 commit comments