@@ -17,6 +17,7 @@ import {
17
17
ContentChild ,
18
18
ContentChildren ,
19
19
ElementRef ,
20
+ inject ,
20
21
Inject ,
21
22
InjectionToken ,
22
23
Input ,
@@ -30,8 +31,8 @@ import {
30
31
import { AbstractControlDirective } from '@angular/forms' ;
31
32
import { ThemePalette } from '@angular/material/core' ;
32
33
import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
33
- import { merge , Subject } from 'rxjs' ;
34
- import { takeUntil } from 'rxjs/operators' ;
34
+ import { EMPTY , merge , Subject } from 'rxjs' ;
35
+ import { finalize , switchMap , takeUntil , tap } from 'rxjs/operators' ;
35
36
import { MAT_ERROR , MatError } from './directives/error' ;
36
37
import {
37
38
FLOATING_LABEL_PARENT ,
@@ -52,6 +53,7 @@ import {
52
53
getMatFormFieldMissingControlError ,
53
54
} from './form-field-errors' ;
54
55
import { DOCUMENT } from '@angular/common' ;
56
+ import { SharedResizeObserver } from '@angular/cdk/observers/private' ;
55
57
56
58
/** Type for the available floatLabel values. */
57
59
export type FloatLabelType = 'always' | 'auto' ;
@@ -284,6 +286,9 @@ export class MatFormField
284
286
private _isFocused : boolean | null = null ;
285
287
private _explicitFormFieldControl : MatFormFieldControl < any > ;
286
288
private _needsOutlineLabelOffsetUpdateOnStable = false ;
289
+ private _needsOutlineLabelPrefixResizeObserverUpdateOnStable = true ;
290
+
291
+ private _resizeObserver = inject ( SharedResizeObserver ) ;
287
292
288
293
constructor (
289
294
public _elementRef : ElementRef ,
@@ -474,9 +479,9 @@ export class MatFormField
474
479
*/
475
480
private _initializeOutlineLabelOffsetSubscriptions ( ) {
476
481
// Whenever the prefix changes, schedule an update of the label offset.
477
- this . _prefixChildren . changes . subscribe (
478
- ( ) => ( this . _needsOutlineLabelOffsetUpdateOnStable = true ) ,
479
- ) ;
482
+ this . _prefixChildren . changes . subscribe ( ( ) => {
483
+ this . _needsOutlineLabelPrefixResizeObserverUpdateOnStable = true ;
484
+ } ) ;
480
485
481
486
// Note that we have to run outside of the `NgZone` explicitly, in order to avoid
482
487
// throwing users into an infinite loop if `zone-patch-rxjs` is included.
@@ -487,6 +492,18 @@ export class MatFormField
487
492
this . _updateOutlineLabelOffset ( ) ;
488
493
}
489
494
} ) ;
495
+
496
+ this . _ngZone . onStable
497
+ . pipe (
498
+ takeUntil ( this . _destroyed ) ,
499
+ switchMap ( ( ) => this . _resizeObserver . observe ( this . _elementRef . nativeElement ) ) ,
500
+ )
501
+ . subscribe ( ( ) => {
502
+ if ( this . _needsOutlineLabelPrefixResizeObserverUpdateOnStable ) {
503
+ this . _needsOutlineLabelPrefixResizeObserverUpdateOnStable = false ;
504
+ this . _updateOutlineLabelOffsetOnPrefixResize ( ) ;
505
+ }
506
+ } ) ;
490
507
} ) ;
491
508
492
509
this . _dir . change
@@ -646,8 +663,8 @@ export class MatFormField
646
663
floatingLabel . style . transform = '' ;
647
664
return ;
648
665
}
649
- // If the form field is not attached to the DOM yet (e.g. in a tab), we defer
650
- // the label offset update until the zone stabilizes.
666
+ // If the form field is invisible (e.g. in a drawer) or not attached to the DOM yet (e.g. in a tab)),
667
+ // we defer the label offset update until the zone stabilizes.
651
668
if ( ! this . _isAttachedToDom ( ) ) {
652
669
this . _needsOutlineLabelOffsetUpdateOnStable = true ;
653
670
return ;
@@ -672,6 +689,23 @@ export class MatFormField
672
689
)` ;
673
690
}
674
691
692
+ /**
693
+ * Updates the horizontal offset of the label in the outline appearance when the prefix containers are resized.
694
+ */
695
+ private _updateOutlineLabelOffsetOnPrefixResize ( ) {
696
+ const iconPrefixContainer = this . _iconPrefixContainer ?. nativeElement ;
697
+ const textPrefixContainer = this . _textPrefixContainer ?. nativeElement ;
698
+
699
+ merge (
700
+ iconPrefixContainer ? this . _resizeObserver . observe ( iconPrefixContainer ) : EMPTY ,
701
+ textPrefixContainer ? this . _resizeObserver . observe ( textPrefixContainer ) : EMPTY ,
702
+ )
703
+ . pipe ( takeUntil ( this . _prefixChildren . changes ) )
704
+ . subscribe ( ( ) => {
705
+ this . _updateOutlineLabelOffset ( ) ;
706
+ } ) ;
707
+ }
708
+
675
709
/** Checks whether the form field is attached to the DOM. */
676
710
private _isAttachedToDom ( ) : boolean {
677
711
const element : HTMLElement = this . _elementRef . nativeElement ;
0 commit comments