Skip to content

Commit 6d95685

Browse files
crisbetoDavidACCarvalhomistrykaran91
authored
Cherry pick fixes (#30715)
* fix(material/select): close panel on detach output event (#30634) * fix(material/autocomplete): allow overlay backdrop by setting hasBackdrop option (#30631) Currently when we open the panel, backdrop is not allowed and is not inline with `mat-select`, `mat-menu`, etc. This fix will align autocomplete with those components and give an option to configure it. Fixes #30457 --------- Co-authored-by: DavidACCarvalho <[email protected]> Co-authored-by: Karan Mistry <[email protected]>
1 parent a46e263 commit 6d95685

File tree

6 files changed

+103
-5
lines changed

6 files changed

+103
-5
lines changed

Diff for: goldens/material/autocomplete/index.api.md

+2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ export interface MatAutocompleteActivatedEvent {
131131
export interface MatAutocompleteDefaultOptions {
132132
autoActiveFirstOption?: boolean;
133133
autoSelectActiveOption?: boolean;
134+
backdropClass?: string;
135+
hasBackdrop?: boolean;
134136
hideSingleSelectionIndicator?: boolean;
135137
overlayPanelClass?: string | string[];
136138
requireSelection?: boolean;

Diff for: src/material/autocomplete/autocomplete-trigger.ts

+2
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,8 @@ export class MatAutocompleteTrigger
899899
scrollStrategy: this._scrollStrategy(),
900900
width: this._getPanelWidth(),
901901
direction: this._dir ?? undefined,
902+
hasBackdrop: this._defaults?.hasBackdrop,
903+
backdropClass: this._defaults?.backdropClass,
902904
panelClass: this._defaults?.overlayPanelClass,
903905
});
904906
}

Diff for: src/material/autocomplete/autocomplete.spec.ts

+48
Original file line numberDiff line numberDiff line change
@@ -3014,6 +3014,54 @@ describe('MatAutocomplete', () => {
30143014
});
30153015
});
30163016

3017+
describe('with backdrop in options', () => {
3018+
it('should not contain backdrop by default', fakeAsync(() => {
3019+
const fixture = createComponent(SimpleAutocomplete, []);
3020+
fixture.detectChanges();
3021+
fixture.componentInstance.trigger.openPanel();
3022+
fixture.detectChanges();
3023+
3024+
tick(500);
3025+
3026+
expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeFalsy();
3027+
}));
3028+
3029+
it('should be able to add the backdrop using hasBackdrop option', fakeAsync(() => {
3030+
const fixture = createComponent(SimpleAutocomplete, [
3031+
{
3032+
provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS,
3033+
useValue: {hasBackdrop: true},
3034+
},
3035+
]);
3036+
fixture.detectChanges();
3037+
fixture.componentInstance.trigger.openPanel();
3038+
fixture.detectChanges();
3039+
3040+
tick(500);
3041+
3042+
expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeTruthy();
3043+
}));
3044+
});
3045+
3046+
describe('with hasBackdrop and backdropClass in options', () => {
3047+
it('should be able to configure custom backdrop class', fakeAsync(() => {
3048+
const fixture = createComponent(SimpleAutocomplete, [
3049+
{
3050+
provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS,
3051+
useValue: {backdropClass: 'my-custom-backdrop-class', hasBackdrop: true},
3052+
},
3053+
]);
3054+
fixture.detectChanges();
3055+
fixture.componentInstance.trigger.openPanel();
3056+
fixture.detectChanges();
3057+
3058+
tick(500);
3059+
3060+
const cdkPanelElement = overlayContainerElement.querySelector('.cdk-overlay-backdrop');
3061+
expect(cdkPanelElement?.classList).toContain('my-custom-backdrop-class');
3062+
}));
3063+
});
3064+
30173065
describe('misc', () => {
30183066
it('should allow basic use without any forms directives', () => {
30193067
expect(() => {

Diff for: src/material/autocomplete/autocomplete.ts

+7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ export interface MatAutocompleteDefaultOptions {
7070
*/
7171
requireSelection?: boolean;
7272

73+
/** Class to be applied to the autocomplete's backdrop. */
74+
backdropClass?: string;
75+
76+
/** Whether the autocomplete has a backdrop. */
77+
hasBackdrop?: boolean;
78+
7379
/** Class or list of classes to be applied to the autocomplete's overlay panel. */
7480
overlayPanelClass?: string | string[];
7581

@@ -97,6 +103,7 @@ export function MAT_AUTOCOMPLETE_DEFAULT_OPTIONS_FACTORY(): MatAutocompleteDefau
97103
autoSelectActiveOption: false,
98104
hideSingleSelectionIndicator: false,
99105
requireSelection: false,
106+
hasBackdrop: false,
100107
};
101108
}
102109

Diff for: src/material/select/select.html

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
[cdkConnectedOverlayPositions]="_positions"
4141
[cdkConnectedOverlayWidth]="_overlayWidth"
4242
[cdkConnectedOverlayFlexibleDimensions]="true"
43+
(detach)="close()"
4344
(backdropClick)="close()"
4445
(overlayKeydown)="_handleOverlayKeydown($event)">
4546
<div

Diff for: src/material/select/select.spec.ts

+43-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
TAB,
1616
UP_ARROW,
1717
} from '@angular/cdk/keycodes';
18-
import {OverlayContainer, OverlayModule} from '@angular/cdk/overlay';
18+
import {CloseScrollStrategy, Overlay, OverlayContainer, OverlayModule} from '@angular/cdk/overlay';
1919
import {ScrollDispatcher} from '@angular/cdk/scrolling';
2020
import {
2121
createKeyboardEvent,
@@ -56,15 +56,15 @@ import {
5656
ReactiveFormsModule,
5757
Validators,
5858
} from '@angular/forms';
59-
import {ErrorStateMatcher, MatOption, MatOptionSelectionChange} from '../core';
60-
import {FloatLabelType, MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormFieldModule} from '../form-field';
61-
import {MAT_SELECT_CONFIG, MatSelectConfig} from '../select';
6259
import {By} from '@angular/platform-browser';
6360
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
6461
import {EMPTY, Observable, Subject, Subscription} from 'rxjs';
6562
import {map} from 'rxjs/operators';
63+
import {ErrorStateMatcher, MatOption, MatOptionSelectionChange} from '../core';
64+
import {FloatLabelType, MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormFieldModule} from '../form-field';
65+
import {MAT_SELECT_CONFIG, MatSelectConfig} from '../select';
6666
import {MatSelectModule} from './index';
67-
import {MatSelect} from './select';
67+
import {MAT_SELECT_SCROLL_STRATEGY, MatSelect} from './select';
6868
import {
6969
getMatSelectDynamicMultipleError,
7070
getMatSelectNonArrayValueError,
@@ -1782,6 +1782,44 @@ describe('MatSelect', () => {
17821782
.withContext('Expected select element to remain focused.')
17831783
.toBe(true);
17841784
}));
1785+
1786+
it('should close the panel on scroll event when MAT_SELECT_SCROLL_STRATEGY token was defined with CloseScrollStrategy', fakeAsync(() => {
1787+
// Need to recreate the testing module, because the issue we're
1788+
// testing for only the MAT_SELECT_SCROLL_STRATEGY is defined with thw
1789+
// is defined with the CloseScrollStrategy
1790+
1791+
TestBed.resetTestingModule();
1792+
TestBed.configureTestingModule({
1793+
imports: [MatFormFieldModule, MatSelectModule],
1794+
declarations: [BasicSelect],
1795+
providers: [
1796+
{
1797+
provide: MAT_SELECT_SCROLL_STRATEGY,
1798+
useFactory: (overlay: Overlay) => (): CloseScrollStrategy =>
1799+
overlay.scrollStrategies.close(),
1800+
deps: [Overlay],
1801+
},
1802+
{
1803+
provide: ScrollDispatcher,
1804+
useFactory: () => ({
1805+
scrolled: () => scrolledSubject,
1806+
}),
1807+
},
1808+
],
1809+
});
1810+
1811+
fixture = TestBed.createComponent(BasicSelect);
1812+
fixture.detectChanges();
1813+
1814+
const select = fixture.componentInstance.select;
1815+
select.open();
1816+
1817+
scrolledSubject.next();
1818+
fixture.detectChanges();
1819+
flush();
1820+
1821+
expect(select.panelOpen).toBe(false);
1822+
}));
17851823
});
17861824

17871825
describe('selection logic', () => {

0 commit comments

Comments
 (0)