Skip to content

Commit 410e2e1

Browse files
committed
fix(form-field): outline gap not being recalculated on direction changes
Since some of the calculations for the outline gap depend on the direction, we need to re-run them of the direction changes.
1 parent 4b15b78 commit 410e2e1

File tree

5 files changed

+51
-10
lines changed

5 files changed

+51
-10
lines changed

src/lib/autocomplete/autocomplete.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {MatOption, MatOptionSelectionChange} from '@angular/material/core';
3636
import {MatFormField, MatFormFieldModule} from '@angular/material/form-field';
3737
import {By} from '@angular/platform-browser';
3838
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
39-
import {Observable, Subject, Subscription} from 'rxjs';
39+
import {Observable, Subject, Subscription, EMPTY} from 'rxjs';
4040
import {map, startWith} from 'rxjs/operators';
4141
import {MatInputModule} from '../input/index';
4242
import {
@@ -485,7 +485,7 @@ describe('MatAutocomplete', () => {
485485

486486
it('should have the correct text direction in RTL', () => {
487487
const rtlFixture = createComponent(SimpleAutocomplete, [
488-
{provide: Directionality, useFactory: () => ({value: 'rtl'})},
488+
{provide: Directionality, useFactory: () => ({value: 'rtl', change: EMPTY})},
489489
]);
490490

491491
rtlFixture.detectChanges();
@@ -498,7 +498,7 @@ describe('MatAutocomplete', () => {
498498
});
499499

500500
it('should update the panel direction if it changes for the trigger', () => {
501-
const dirProvider = {value: 'rtl'};
501+
const dirProvider = {value: 'rtl', change: EMPTY};
502502
const rtlFixture = createComponent(SimpleAutocomplete, [
503503
{provide: Directionality, useFactory: () => dirProvider},
504504
]);

src/lib/chips/chip-input.spec.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
77
import {By} from '@angular/platform-browser';
88
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
99
import {MatFormFieldModule} from '@angular/material/form-field';
10+
import {EMPTY} from 'rxjs';
1011
import {MatChipInput, MatChipInputEvent} from './chip-input';
1112
import {MatChipsModule} from './index';
1213
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
@@ -27,7 +28,7 @@ describe('MatChipInput', () => {
2728
declarations: [TestChipInput],
2829
providers: [{
2930
provide: Directionality, useFactory: () => {
30-
return {value: dir.toLowerCase()};
31+
return {value: dir.toLowerCase(), change: EMPTY};
3132
}
3233
}]
3334
});

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

+14-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
QueryList,
2727
ViewChild,
2828
ViewEncapsulation,
29+
OnDestroy,
2930
} from '@angular/core';
3031
import {
3132
CanColor, CanColorCtor,
@@ -34,8 +35,8 @@ import {
3435
MAT_LABEL_GLOBAL_OPTIONS,
3536
mixinColor,
3637
} from '@angular/material/core';
37-
import {fromEvent, merge} from 'rxjs';
38-
import {startWith, take} from 'rxjs/operators';
38+
import {fromEvent, merge, Subject} from 'rxjs';
39+
import {startWith, take, takeUntil} from 'rxjs/operators';
3940
import {MatError} from './error';
4041
import {matFormFieldAnimations} from './form-field-animations';
4142
import {MatFormFieldControl} from './form-field-control';
@@ -141,9 +142,10 @@ export const MAT_FORM_FIELD_DEFAULT_OPTIONS =
141142
})
142143

143144
export class MatFormField extends _MatFormFieldMixinBase
144-
implements AfterContentInit, AfterContentChecked, AfterViewInit, CanColor {
145+
implements AfterContentInit, AfterContentChecked, AfterViewInit, OnDestroy, CanColor {
145146
private _labelOptions: LabelOptions;
146147
private _outlineGapCalculationNeeded = false;
148+
private _destroyed = new Subject<void>();
147149

148150
/** The form-field appearance style. */
149151
@Input()
@@ -303,6 +305,10 @@ export class MatFormField extends _MatFormFieldMixinBase
303305
this._syncDescribedByIds();
304306
this._changeDetectorRef.markForCheck();
305307
});
308+
309+
if (this._dir) {
310+
this._dir.change.pipe(takeUntil(this._destroyed)).subscribe(() => this.updateOutlineGap());
311+
}
306312
}
307313

308314
ngAfterContentChecked() {
@@ -318,6 +324,11 @@ export class MatFormField extends _MatFormFieldMixinBase
318324
this._changeDetectorRef.detectChanges();
319325
}
320326

327+
ngOnDestroy() {
328+
this._destroyed.next();
329+
this._destroyed.complete();
330+
}
331+
321332
/** Determines whether a class from the NgControl should be forwarded to the host element. */
322333
_shouldForward(prop: keyof NgControl): boolean {
323334
const ngControl = this._control ? this._control.ngControl : null;

src/lib/input/input.spec.ts

+29
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ import {By} from '@angular/platform-browser';
4343
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
4444
import {MatStepperModule} from '@angular/material/stepper';
4545
import {MatTabsModule} from '@angular/material/tabs';
46+
import {Directionality, Direction} from '@angular/cdk/bidi';
47+
import {Subject} from 'rxjs';
4648
import {MatInputModule, MatInput, MAT_INPUT_VALUE_ACCESSOR} from './index';
4749
import {MatTextareaAutosize} from './autosize';
4850

@@ -1340,6 +1342,33 @@ describe('MatInput with appearance', () => {
13401342
expect(outlineFixture.componentInstance.formField.updateOutlineGap).toHaveBeenCalled();
13411343
}));
13421344

1345+
it('should update the outline gap if the direction changes', fakeAsync(() => {
1346+
fixture.destroy();
1347+
TestBed.resetTestingModule();
1348+
1349+
const fakeDirectionality = {change: new Subject<Direction>(), value: 'ltr'};
1350+
const outlineFixture = createComponent(MatInputWithAppearanceAndLabel, [{
1351+
provide: Directionality,
1352+
useValue: fakeDirectionality
1353+
}]);
1354+
1355+
outlineFixture.componentInstance.appearance = 'outline';
1356+
outlineFixture.detectChanges();
1357+
flush();
1358+
outlineFixture.detectChanges();
1359+
1360+
spyOn(outlineFixture.componentInstance.formField, 'updateOutlineGap');
1361+
1362+
fakeDirectionality.value = 'rtl';
1363+
fakeDirectionality.change.next('rtl');
1364+
outlineFixture.detectChanges();
1365+
flush();
1366+
outlineFixture.detectChanges();
1367+
1368+
expect(outlineFixture.componentInstance.formField.updateOutlineGap).toHaveBeenCalled();
1369+
}));
1370+
1371+
13431372

13441373
});
13451374

src/lib/select/select.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import {
5959
import {MatFormFieldModule} from '@angular/material/form-field';
6060
import {By} from '@angular/platform-browser';
6161
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
62-
import {Subject, Subscription} from 'rxjs';
62+
import {Subject, Subscription, EMPTY, Observable} from 'rxjs';
6363
import {map} from 'rxjs/operators';
6464
import {MatSelectModule} from './index';
6565
import {MatSelect} from './select';
@@ -76,7 +76,7 @@ const LETTER_KEY_DEBOUNCE_INTERVAL = 200;
7676
describe('MatSelect', () => {
7777
let overlayContainer: OverlayContainer;
7878
let overlayContainerElement: HTMLElement;
79-
let dir: {value: 'ltr'|'rtl'};
79+
let dir: {value: 'ltr'|'rtl', change: Observable<string>};
8080
let scrolledSubject = new Subject();
8181
let viewportRuler: ViewportRuler;
8282
let platform: Platform;
@@ -98,7 +98,7 @@ describe('MatSelect', () => {
9898
],
9999
declarations: declarations,
100100
providers: [
101-
{provide: Directionality, useFactory: () => dir = {value: 'ltr'}},
101+
{provide: Directionality, useFactory: () => dir = {value: 'ltr', change: EMPTY}},
102102
{
103103
provide: ScrollDispatcher, useFactory: () => ({
104104
scrolled: () => scrolledSubject.asObservable(),

0 commit comments

Comments
 (0)