Skip to content

Commit 8e49388

Browse files
crisbetojelbourn
authored andcommitted
fix(form-field): outline gap not calculated when appearance is provided through DI (#12767)
Fixes the outline gap not being calculated if the `appearance` is set through the default options, because it doesn't go through the setter and we're not guaranteed for the `MutationObserver` callback to fire at the right time. Fixes #12765.
1 parent 21095f5 commit 8e49388

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

src/lib/form-field/form-field.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ export class MatFormField extends _MatFormFieldMixinBase
145145

146146
/** The form-field appearance style. */
147147
@Input()
148-
get appearance(): MatFormFieldAppearance {
149-
return this._appearance || this._defaultOptions && this._defaultOptions.appearance || 'legacy';
150-
}
148+
get appearance(): MatFormFieldAppearance { return this._appearance; }
151149
set appearance(value: MatFormFieldAppearance) {
152150
const oldValue = this._appearance;
153-
this._appearance = value;
151+
152+
this._appearance = value || (this._defaults && this._defaults.appearance) || 'legacy';
153+
154154
if (this._appearance === 'outline' && oldValue !== value) {
155155
// @breaking-change 7.0.0 Remove this check and else block once _ngZone is required.
156156
if (this._ngZone) {
@@ -246,8 +246,8 @@ export class MatFormField extends _MatFormFieldMixinBase
246246
private _changeDetectorRef: ChangeDetectorRef,
247247
@Optional() @Inject(MAT_LABEL_GLOBAL_OPTIONS) labelOptions: LabelOptions,
248248
@Optional() private _dir: Directionality,
249-
@Optional() @Inject(MAT_FORM_FIELD_DEFAULT_OPTIONS) private _defaultOptions:
250-
MatFormFieldDefaultOptions,
249+
@Optional() @Inject(MAT_FORM_FIELD_DEFAULT_OPTIONS)
250+
private _defaults: MatFormFieldDefaultOptions,
251251
// @breaking-change 7.0.0 _platform, _ngZone and _animationMode to be made required.
252252
private _platform?: Platform,
253253
private _ngZone?: NgZone,
@@ -257,6 +257,9 @@ export class MatFormField extends _MatFormFieldMixinBase
257257
this._labelOptions = labelOptions ? labelOptions : {};
258258
this.floatLabel = this._labelOptions.float || 'auto';
259259
this._animationsEnabled = _animationMode !== 'NoopAnimations';
260+
261+
// Set the default through here so we invoke the setter on the first run.
262+
this.appearance = (_defaults && _defaults.appearance) ? _defaults.appearance : 'legacy';
260263
}
261264

262265
/**

src/lib/input/input.spec.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import {Platform, PlatformModule} from '@angular/cdk/platform';
2-
import {createFakeEvent, dispatchFakeEvent, wrappedErrorMessage} from '@angular/cdk/testing';
3-
import {ChangeDetectionStrategy, Component, ViewChild, Type, Provider} from '@angular/core';
2+
import {
3+
createFakeEvent,
4+
dispatchFakeEvent,
5+
wrappedErrorMessage,
6+
MockNgZone,
7+
} from '@angular/cdk/testing';
8+
import {ChangeDetectionStrategy, Component, ViewChild, Type, Provider, NgZone} from '@angular/core';
49
import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing';
510
import {
611
FormControl,
@@ -28,10 +33,10 @@ import {
2833
} from '@angular/material/form-field';
2934
import {By} from '@angular/platform-browser';
3035
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
31-
import {MatInputModule} from './index';
32-
import {MatInput} from './input';
3336
import {MatStepperModule} from '@angular/material/stepper';
3437
import {MatTabsModule} from '@angular/material/tabs';
38+
import {MatInputModule} from './index';
39+
import {MatInput} from './input';
3540
import {MatTextareaAutosize} from './autosize';
3641

3742
describe('MatInput without forms', () => {
@@ -1170,6 +1175,35 @@ describe('MatInput with appearance', () => {
11701175
expect(parseInt(outlineGap.style.width)).toBeFalsy();
11711176
}));
11721177

1178+
it('should calculate the gaps if the default appearance is provided through DI', fakeAsync(() => {
1179+
fixture.destroy();
1180+
TestBed.resetTestingModule();
1181+
1182+
let zone: MockNgZone;
1183+
const labelFixture = createComponent(MatInputWithLabel, [
1184+
{
1185+
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
1186+
useValue: {appearance: 'outline'}
1187+
},
1188+
{
1189+
provide: NgZone,
1190+
useFactory: () => zone = new MockNgZone()
1191+
}
1192+
]);
1193+
1194+
labelFixture.detectChanges();
1195+
zone!.simulateZoneExit();
1196+
flush();
1197+
labelFixture.detectChanges();
1198+
1199+
const wrapperElement = labelFixture.nativeElement;
1200+
const outlineStart = wrapperElement.querySelector('.mat-form-field-outline-start');
1201+
const outlineGap = wrapperElement.querySelector('.mat-form-field-outline-gap');
1202+
1203+
expect(parseInt(outlineStart.style.width)).toBeGreaterThan(0);
1204+
expect(parseInt(outlineGap.style.width)).toBeGreaterThan(0);
1205+
}));
1206+
11731207
});
11741208

11751209
describe('MatFormField default options', () => {
@@ -1586,6 +1620,16 @@ class MatInputOnPush {
15861620
})
15871621
class MatInputWithReadonlyInput {}
15881622

1623+
@Component({
1624+
template: `
1625+
<mat-form-field>
1626+
<mat-label>Label</mat-label>
1627+
<input matInput>
1628+
</mat-form-field>
1629+
`
1630+
})
1631+
class MatInputWithLabel {}
1632+
15891633
@Component({
15901634
template: `
15911635
<mat-form-field [floatLabel]="floatLabel">

0 commit comments

Comments
 (0)