@@ -37,7 +37,7 @@ import {
37
37
} from '@angular/core' ;
38
38
import { AbstractControlDirective } from '@angular/forms' ;
39
39
import { ThemePalette } from '@angular/material/core' ;
40
- import { Subject , merge } from 'rxjs' ;
40
+ import { Subject , Subscription , merge } from 'rxjs' ;
41
41
import { takeUntil } from 'rxjs/operators' ;
42
42
import { MAT_ERROR , MatError } from './directives/error' ;
43
43
import {
@@ -318,6 +318,9 @@ export class MatFormField
318
318
private _isFocused : boolean | null = null ;
319
319
private _explicitFormFieldControl : MatFormFieldControl < any > ;
320
320
private _needsOutlineLabelOffsetUpdate = false ;
321
+ private _previousControl : MatFormFieldControl < unknown > | null = null ;
322
+ private _stateChanges : Subscription | undefined ;
323
+ private _valueChanges : Subscription | undefined ;
321
324
322
325
private _injector = inject ( Injector ) ;
323
326
@@ -365,17 +368,23 @@ export class MatFormField
365
368
366
369
ngAfterContentInit ( ) {
367
370
this . _assertFormFieldControl ( ) ;
368
- this . _initializeControl ( ) ;
369
371
this . _initializeSubscript ( ) ;
370
372
this . _initializePrefixAndSuffix ( ) ;
371
373
this . _initializeOutlineLabelOffsetSubscriptions ( ) ;
372
374
}
373
375
374
376
ngAfterContentChecked ( ) {
375
377
this . _assertFormFieldControl ( ) ;
378
+
379
+ if ( this . _control !== this . _previousControl ) {
380
+ this . _initializeControl ( this . _previousControl ) ;
381
+ this . _previousControl = this . _control ;
382
+ }
376
383
}
377
384
378
385
ngOnDestroy ( ) {
386
+ this . _stateChanges ?. unsubscribe ( ) ;
387
+ this . _valueChanges ?. unsubscribe ( ) ;
379
388
this . _destroyed . next ( ) ;
380
389
this . _destroyed . complete ( ) ;
381
390
}
@@ -409,25 +418,31 @@ export class MatFormField
409
418
}
410
419
411
420
/** Initializes the registered form field control. */
412
- private _initializeControl ( ) {
421
+ private _initializeControl ( previousControl : MatFormFieldControl < unknown > | null ) {
413
422
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
+ }
414
428
415
429
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 ) ;
419
431
}
420
432
421
433
// 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 ( ( ) => {
423
436
this . _updateFocusState ( ) ;
424
437
this . _syncDescribedByIds ( ) ;
425
438
this . _changeDetectorRef . markForCheck ( ) ;
426
439
} ) ;
427
440
441
+ this . _valueChanges ?. unsubscribe ( ) ;
442
+
428
443
// Run change detection if the value changes.
429
444
if ( control . ngControl && control . ngControl . valueChanges ) {
430
- control . ngControl . valueChanges
445
+ this . _valueChanges = control . ngControl . valueChanges
431
446
. pipe ( takeUntil ( this . _destroyed ) )
432
447
. subscribe ( ( ) => this . _changeDetectorRef . markForCheck ( ) ) ;
433
448
}
0 commit comments