@@ -19,6 +19,8 @@ import {
1919 ElementRef ,
2020 Inject ,
2121 InjectionToken ,
22+ Injector ,
23+ inject ,
2224 Input ,
2325 NgZone ,
2426 OnDestroy ,
@@ -27,6 +29,7 @@ import {
2729 ViewChild ,
2830 ViewEncapsulation ,
2931 ANIMATION_MODULE_TYPE ,
32+ afterRender ,
3033} from '@angular/core' ;
3134import { AbstractControlDirective } from '@angular/forms' ;
3235import { ThemePalette } from '@angular/material/core' ;
@@ -245,7 +248,7 @@ export class MatFormField
245248 // If the appearance has been switched to `outline`, the label offset needs to be updated.
246249 // The update can happen once the view has been re-checked, but not immediately because
247250 // the view has not been updated and the notched-outline floating label is not present.
248- this . _needsOutlineLabelOffsetUpdateOnStable = true ;
251+ this . _needsOutlineLabelOffsetUpdate = true ;
249252 }
250253 }
251254 private _appearance : MatFormFieldAppearance = DEFAULT_APPEARANCE ;
@@ -300,12 +303,18 @@ export class MatFormField
300303 private _destroyed = new Subject < void > ( ) ;
301304 private _isFocused : boolean | null = null ;
302305 private _explicitFormFieldControl : MatFormFieldControl < any > ;
303- private _needsOutlineLabelOffsetUpdateOnStable = false ;
306+ private _needsOutlineLabelOffsetUpdate = false ;
307+
308+ private _injector = inject ( Injector ) ;
304309
305310 constructor (
306311 public _elementRef : ElementRef ,
307312 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 ,
309318 private _dir : Directionality ,
310319 private _platform : Platform ,
311320 @Optional ( )
@@ -485,30 +494,30 @@ export class MatFormField
485494 * The floating label in the docked state needs to account for prefixes. The horizontal offset
486495 * is calculated whenever the appearance changes to `outline`, the prefixes change, or when the
487496 * 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.
491498 */
492499 private _initializeOutlineLabelOffsetSubscriptions ( ) {
493500 // 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 ;
504510 this . _updateOutlineLabelOffset ( ) ;
505511 }
506- } ) ;
507- } ) ;
512+ } ,
513+ {
514+ injector : this . _injector ,
515+ } ,
516+ ) ;
508517
509518 this . _dir . change
510519 . pipe ( takeUntil ( this . _destroyed ) )
511- . subscribe ( ( ) => ( this . _needsOutlineLabelOffsetUpdateOnStable = true ) ) ;
520+ . subscribe ( ( ) => ( this . _needsOutlineLabelOffsetUpdate = true ) ) ;
512521 }
513522
514523 /** Whether the floating label should always float or not. */
@@ -653,7 +662,7 @@ export class MatFormField
653662 * incorporate the horizontal offset into their default text-field styles.
654663 */
655664 private _updateOutlineLabelOffset ( ) {
656- if ( ! this . _platform . isBrowser || ! this . _hasOutline ( ) || ! this . _floatingLabel ) {
665+ if ( ! this . _hasOutline ( ) || ! this . _floatingLabel ) {
657666 return ;
658667 }
659668 const floatingLabel = this . _floatingLabel . element ;
@@ -666,7 +675,7 @@ export class MatFormField
666675 // If the form field is not attached to the DOM yet (e.g. in a tab), we defer
667676 // the label offset update until the zone stabilizes.
668677 if ( ! this . _isAttachedToDom ( ) ) {
669- this . _needsOutlineLabelOffsetUpdateOnStable = true ;
678+ this . _needsOutlineLabelOffsetUpdate = true ;
670679 return ;
671680 }
672681 const iconPrefixContainer = this . _iconPrefixContainer ?. nativeElement ;
0 commit comments