fix(form-field): not updating outline when prefix/suffix is added or removed (#13253)

Fixes the form field's outline not reacting to the prefix/suffix being toggled after init.

Fixes #13251.
This commit is contained in:
Kristiyan Kostadinov
2018-10-05 20:12:58 +02:00
committed by vivian-hu
parent 1c60acf728
commit 0060bd7ec8
2 changed files with 53 additions and 17 deletions
+28 -17
View File
@@ -34,7 +34,7 @@ import {
MAT_LABEL_GLOBAL_OPTIONS,
mixinColor,
} from '@angular/material/core';
import {EMPTY, fromEvent, merge} from 'rxjs';
import {fromEvent, merge} from 'rxjs';
import {startWith, take} from 'rxjs/operators';
import {MatError} from './error';
import {matFormFieldAnimations} from './form-field-animations';
@@ -154,14 +154,7 @@ export class MatFormField extends _MatFormFieldMixinBase
this._appearance = value || (this._defaults && this._defaults.appearance) || 'legacy';
if (this._appearance === 'outline' && oldValue !== value) {
// @breaking-change 7.0.0 Remove this check and else block once _ngZone is required.
if (this._ngZone) {
this._ngZone!.onStable.pipe(take(1)).subscribe(() => {
this._ngZone!.runOutsideAngular(() => this.updateOutlineGap());
});
} else {
Promise.resolve().then(() => this.updateOutlineGap());
}
this._updateOutlineGapOnStable();
}
}
_appearance: MatFormFieldAppearance;
@@ -274,22 +267,30 @@ export class MatFormField extends _MatFormFieldMixinBase
ngAfterContentInit() {
this._validateControlChild();
if (this._control.controlType) {
this._elementRef.nativeElement.classList
.add(`mat-form-field-type-${this._control.controlType}`);
const control = this._control;
if (control.controlType) {
this._elementRef.nativeElement.classList.add(`mat-form-field-type-${control.controlType}`);
}
// Subscribe to changes in the child control state in order to update the form field UI.
this._control.stateChanges.pipe(startWith<void>(null!)).subscribe(() => {
control.stateChanges.pipe(startWith<void>(null!)).subscribe(() => {
this._validatePlaceholders();
this._syncDescribedByIds();
this._changeDetectorRef.markForCheck();
});
// Run change detection if the value, prefix, or suffix changes.
const valueChanges = this._control.ngControl && this._control.ngControl.valueChanges || EMPTY;
merge(valueChanges, this._prefixChildren.changes, this._suffixChildren.changes)
.subscribe(() => this._changeDetectorRef.markForCheck());
// Run change detection if the value changes.
if (control.ngControl && control.ngControl.valueChanges) {
control.ngControl.valueChanges.subscribe(() => this._changeDetectorRef.markForCheck());
}
// Run change detection and update the outline if the suffix or prefix changes.
merge(this._prefixChildren.changes, this._suffixChildren.changes).subscribe(() => {
this._updateOutlineGapOnStable();
this._changeDetectorRef.markForCheck();
});
// Re-validate when the number of hints changes.
this._hintChildren.changes.pipe(startWith(null)).subscribe(() => {
@@ -504,4 +505,14 @@ export class MatFormField extends _MatFormFieldMixinBase
private _getStartEnd(rect: ClientRect): number {
return this._dir && this._dir.value === 'rtl' ? rect.right : rect.left;
}
/** Updates the outline gap the new time the zone stabilizes. */
private _updateOutlineGapOnStable() {
// @breaking-change 7.0.0 Remove this check and else block once _ngZone is required.
if (this._ngZone) {
this._ngZone.onStable.pipe(take(1)).subscribe(() => this.updateOutlineGap());
} else {
Promise.resolve().then(() => this.updateOutlineGap());
}
}
}
+25
View File
@@ -1319,6 +1319,28 @@ describe('MatInput with appearance', () => {
expect(parseInt(outlineGap.style.width)).toBeGreaterThan(0);
}));
it('should update the outline gap when the prefix/suffix is added or removed', fakeAsync(() => {
fixture.destroy();
TestBed.resetTestingModule();
const outlineFixture = createComponent(MatInputWithAppearanceAndLabel);
outlineFixture.componentInstance.appearance = 'outline';
outlineFixture.detectChanges();
flush();
outlineFixture.detectChanges();
spyOn(outlineFixture.componentInstance.formField, 'updateOutlineGap');
outlineFixture.componentInstance.showPrefix = true;
outlineFixture.detectChanges();
flush();
outlineFixture.detectChanges();
expect(outlineFixture.componentInstance.formField.updateOutlineGap).toHaveBeenCalled();
}));
});
describe('MatFormField default options', () => {
@@ -1774,13 +1796,16 @@ class MatInputWithAppearance {
@Component({
template: `
<mat-form-field [appearance]="appearance">
<span matPrefix *ngIf="showPrefix">Somewhat long prefix</span>
<mat-label>{{labelContent}}</mat-label>
<input matInput>
</mat-form-field>
`
})
class MatInputWithAppearanceAndLabel {
@ViewChild(MatFormField) formField: MatFormField;
appearance: MatFormFieldAppearance;
showPrefix: boolean;
labelContent = 'Label';
}