@@ -37,7 +37,7 @@ import {
3737} from '@angular/core' ;
3838import { AbstractControlDirective } from '@angular/forms' ;
3939import { ThemePalette } from '@angular/material/core' ;
40- import { Subject , merge } from 'rxjs' ;
40+ import { Subject , Subscription , merge } from 'rxjs' ;
4141import { takeUntil } from 'rxjs/operators' ;
4242import { MAT_ERROR , MatError } from './directives/error' ;
4343import {
@@ -318,6 +318,9 @@ export class MatFormField
318318 private _isFocused : boolean | null = null ;
319319 private _explicitFormFieldControl : MatFormFieldControl < any > ;
320320 private _needsOutlineLabelOffsetUpdate = false ;
321+ private _previousControl : MatFormFieldControl < unknown > | null = null ;
322+ private _stateChanges : Subscription | undefined ;
323+ private _valueChanges : Subscription | undefined ;
321324
322325 private _injector = inject ( Injector ) ;
323326
@@ -365,17 +368,23 @@ export class MatFormField
365368
366369 ngAfterContentInit ( ) {
367370 this . _assertFormFieldControl ( ) ;
368- this . _initializeControl ( ) ;
369371 this . _initializeSubscript ( ) ;
370372 this . _initializePrefixAndSuffix ( ) ;
371373 this . _initializeOutlineLabelOffsetSubscriptions ( ) ;
372374 }
373375
374376 ngAfterContentChecked ( ) {
375377 this . _assertFormFieldControl ( ) ;
378+
379+ if ( this . _control !== this . _previousControl ) {
380+ this . _initializeControl ( this . _previousControl ) ;
381+ this . _previousControl = this . _control ;
382+ }
376383 }
377384
378385 ngOnDestroy ( ) {
386+ this . _stateChanges ?. unsubscribe ( ) ;
387+ this . _valueChanges ?. unsubscribe ( ) ;
379388 this . _destroyed . next ( ) ;
380389 this . _destroyed . complete ( ) ;
381390 }
@@ -409,25 +418,31 @@ export class MatFormField
409418 }
410419
411420 /** Initializes the registered form field control. */
412- private _initializeControl ( ) {
421+ private _initializeControl ( previousControl : MatFormFieldControl < unknown > | null ) {
413422 const control = this . _control ;
423+ const classPrefix = 'mat-mdc-form-field-type-' ;
424+
425+ if ( previousControl ) {
426+ this . _elementRef . nativeElement . classList . remove ( classPrefix + previousControl . controlType ) ;
427+ }
414428
415429 if ( control . controlType ) {
416- this . _elementRef . nativeElement . classList . add (
417- `mat-mdc-form-field-type-${ control . controlType } ` ,
418- ) ;
430+ this . _elementRef . nativeElement . classList . add ( classPrefix + control . controlType ) ;
419431 }
420432
421433 // Subscribe to changes in the child control state in order to update the form field UI.
422- control . stateChanges . subscribe ( ( ) => {
434+ this . _stateChanges ?. unsubscribe ( ) ;
435+ this . _stateChanges = control . stateChanges . subscribe ( ( ) => {
423436 this . _updateFocusState ( ) ;
424437 this . _syncDescribedByIds ( ) ;
425438 this . _changeDetectorRef . markForCheck ( ) ;
426439 } ) ;
427440
441+ this . _valueChanges ?. unsubscribe ( ) ;
442+
428443 // Run change detection if the value changes.
429444 if ( control . ngControl && control . ngControl . valueChanges ) {
430- control . ngControl . valueChanges
445+ this . _valueChanges = control . ngControl . valueChanges
431446 . pipe ( takeUntil ( this . _destroyed ) )
432447 . subscribe ( ( ) => this . _changeDetectorRef . markForCheck ( ) ) ;
433448 }
0 commit comments