mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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:
committed by
vivian-hu
parent
1c60acf728
commit
0060bd7ec8
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user