Skip to content

Commit 413fe33

Browse files
crisbetojelbourn
authored andcommitted
fix(autocomplete): remove old classes when classlist has changed (#15185)
Currently we have some logic that syncs the classes between the autocomplete host element and the panel, however this logic doesn't account for classes being removed. Fixes #15179.
1 parent a115b3a commit 413fe33

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

src/lib/autocomplete/autocomplete.spec.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,31 @@ describe('MatAutocomplete', () => {
19661966
expect(panel.classList).toContain('class-two');
19671967
}));
19681968

1969+
it('should remove old classes when the panel class changes', fakeAsync(() => {
1970+
const fixture = createComponent(SimpleAutocomplete);
1971+
fixture.detectChanges();
1972+
1973+
fixture.componentInstance.trigger.openPanel();
1974+
tick();
1975+
fixture.detectChanges();
1976+
1977+
const classList =
1978+
overlayContainerElement.querySelector('.mat-autocomplete-panel')!.classList;
1979+
1980+
expect(classList).toContain('mat-autocomplete-visible');
1981+
expect(classList).toContain('class-one');
1982+
expect(classList).toContain('class-two');
1983+
1984+
fixture.componentInstance.panelClass = 'class-three class-four';
1985+
fixture.detectChanges();
1986+
1987+
expect(classList).not.toContain('class-one');
1988+
expect(classList).not.toContain('class-two');
1989+
expect(classList).toContain('mat-autocomplete-visible');
1990+
expect(classList).toContain('class-three');
1991+
expect(classList).toContain('class-four');
1992+
}));
1993+
19691994
it('should reset correctly when closed programmatically', fakeAsync(() => {
19701995
const scrolledSubject = new Subject();
19711996
const fixture = createComponent(SimpleAutocomplete, [
@@ -2307,7 +2332,7 @@ describe('MatAutocomplete', () => {
23072332
[formControl]="stateCtrl">
23082333
</mat-form-field>
23092334
2310-
<mat-autocomplete class="class-one class-two" #auto="matAutocomplete" [displayWith]="displayFn"
2335+
<mat-autocomplete [class]="panelClass" #auto="matAutocomplete" [displayWith]="displayFn"
23112336
[disableRipple]="disableRipple" (opened)="openedSpy()" (closed)="closedSpy()">
23122337
<mat-option *ngFor="let state of filteredStates" [value]="state">
23132338
<span>{{ state.code }}: {{ state.name }}</span>
@@ -2323,6 +2348,7 @@ class SimpleAutocomplete implements OnDestroy {
23232348
width: number;
23242349
disableRipple = false;
23252350
autocompleteDisabled = false;
2351+
panelClass = 'class-one class-two';
23262352
openedSpy = jasmine.createSpy('autocomplete opened spy');
23272353
closedSpy = jasmine.createSpy('autocomplete closed spy');
23282354

@@ -2361,7 +2387,6 @@ class SimpleAutocomplete implements OnDestroy {
23612387
ngOnDestroy() {
23622388
this.valueSub.unsubscribe();
23632389
}
2364-
23652390
}
23662391

23672392
@Component({

src/lib/autocomplete/autocomplete.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,16 @@ export class MatAutocomplete extends _MatAutocompleteMixinBase implements AfterC
153153
@Input('class')
154154
set classList(value: string) {
155155
if (value && value.length) {
156-
value.split(' ').forEach(className => this._classList[className.trim()] = true);
157-
this._elementRef.nativeElement.className = '';
156+
this._classList = value.split(' ').reduce((classList, className) => {
157+
classList[className.trim()] = true;
158+
return classList;
159+
}, {} as {[key: string]: boolean});
160+
} else {
161+
this._classList = {};
158162
}
163+
164+
this._setVisibilityClasses(this._classList);
165+
this._elementRef.nativeElement.className = '';
159166
}
160167
_classList: {[key: string]: boolean} = {};
161168

@@ -195,8 +202,7 @@ export class MatAutocomplete extends _MatAutocompleteMixinBase implements AfterC
195202
/** Panel should hide itself when the option list is empty. */
196203
_setVisibility() {
197204
this.showPanel = !!this.options.length;
198-
this._classList['mat-autocomplete-visible'] = this.showPanel;
199-
this._classList['mat-autocomplete-hidden'] = !this.showPanel;
205+
this._setVisibilityClasses(this._classList);
200206
this._changeDetectorRef.markForCheck();
201207
}
202208

@@ -205,5 +211,11 @@ export class MatAutocomplete extends _MatAutocompleteMixinBase implements AfterC
205211
const event = new MatAutocompleteSelectedEvent(this, option);
206212
this.optionSelected.emit(event);
207213
}
214+
215+
/** Sets the autocomplete visibility classes on a classlist based on the panel is visible. */
216+
private _setVisibilityClasses(classList: {[key: string]: boolean}) {
217+
classList['mat-autocomplete-visible'] = this.showPanel;
218+
classList['mat-autocomplete-hidden'] = !this.showPanel;
219+
}
208220
}
209221

0 commit comments

Comments
 (0)