From ad3be3cd65fa91736658250260bbdf400b9c65cb Mon Sep 17 00:00:00 2001 From: DavidACCarvalho <85346154+DavidACCarvalho@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:54:39 +0000 Subject: [PATCH 1/2] fix(material/select): close panel on detach output event (#30634) --- src/material/select/select.html | 1 + src/material/select/select.spec.ts | 48 ++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/material/select/select.html b/src/material/select/select.html index 9a9b147c3c51..6eaecee7f5c3 100644 --- a/src/material/select/select.html +++ b/src/material/select/select.html @@ -40,6 +40,7 @@ [cdkConnectedOverlayPositions]="_positions" [cdkConnectedOverlayWidth]="_overlayWidth" [cdkConnectedOverlayFlexibleDimensions]="true" + (detach)="close()" (backdropClick)="close()" (overlayKeydown)="_handleOverlayKeydown($event)">
{ .withContext('Expected select element to remain focused.') .toBe(true); })); + + it('should close the panel on scroll event when MAT_SELECT_SCROLL_STRATEGY token was defined with CloseScrollStrategy', fakeAsync(() => { + // Need to recreate the testing module, because the issue we're + // testing for only the MAT_SELECT_SCROLL_STRATEGY is defined with thw + // is defined with the CloseScrollStrategy + + TestBed.resetTestingModule(); + TestBed.configureTestingModule({ + imports: [MatFormFieldModule, MatSelectModule], + declarations: [BasicSelect], + providers: [ + { + provide: MAT_SELECT_SCROLL_STRATEGY, + useFactory: (overlay: Overlay) => (): CloseScrollStrategy => + overlay.scrollStrategies.close(), + deps: [Overlay], + }, + { + provide: ScrollDispatcher, + useFactory: () => ({ + scrolled: () => scrolledSubject, + }), + }, + ], + }); + + fixture = TestBed.createComponent(BasicSelect); + fixture.detectChanges(); + + const select = fixture.componentInstance.select; + select.open(); + + scrolledSubject.next(); + fixture.detectChanges(); + flush(); + + expect(select.panelOpen).toBe(false); + })); }); describe('selection logic', () => { From e23bbdfe08c196c51dae0e75094f1abdf9d3cac6 Mon Sep 17 00:00:00 2001 From: Karan Mistry Date: Tue, 18 Mar 2025 20:52:06 +0530 Subject: [PATCH 2/2] 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 --- goldens/material/autocomplete/index.api.md | 2 + .../autocomplete/autocomplete-trigger.ts | 2 + .../autocomplete/autocomplete.spec.ts | 48 +++++++++++++++++++ src/material/autocomplete/autocomplete.ts | 7 +++ 4 files changed, 59 insertions(+) diff --git a/goldens/material/autocomplete/index.api.md b/goldens/material/autocomplete/index.api.md index edc45ad80fae..912850144c22 100644 --- a/goldens/material/autocomplete/index.api.md +++ b/goldens/material/autocomplete/index.api.md @@ -131,6 +131,8 @@ export interface MatAutocompleteActivatedEvent { export interface MatAutocompleteDefaultOptions { autoActiveFirstOption?: boolean; autoSelectActiveOption?: boolean; + backdropClass?: string; + hasBackdrop?: boolean; hideSingleSelectionIndicator?: boolean; overlayPanelClass?: string | string[]; requireSelection?: boolean; diff --git a/src/material/autocomplete/autocomplete-trigger.ts b/src/material/autocomplete/autocomplete-trigger.ts index 5127fd85fecd..22f2f93f3cd3 100644 --- a/src/material/autocomplete/autocomplete-trigger.ts +++ b/src/material/autocomplete/autocomplete-trigger.ts @@ -899,6 +899,8 @@ export class MatAutocompleteTrigger scrollStrategy: this._scrollStrategy(), width: this._getPanelWidth(), direction: this._dir ?? undefined, + hasBackdrop: this._defaults?.hasBackdrop, + backdropClass: this._defaults?.backdropClass, panelClass: this._defaults?.overlayPanelClass, }); } diff --git a/src/material/autocomplete/autocomplete.spec.ts b/src/material/autocomplete/autocomplete.spec.ts index 2b7bb5ba3f8b..9a27005487f9 100644 --- a/src/material/autocomplete/autocomplete.spec.ts +++ b/src/material/autocomplete/autocomplete.spec.ts @@ -3014,6 +3014,54 @@ describe('MatAutocomplete', () => { }); }); + describe('with backdrop in options', () => { + it('should not contain backdrop by default', fakeAsync(() => { + const fixture = createComponent(SimpleAutocomplete, []); + fixture.detectChanges(); + fixture.componentInstance.trigger.openPanel(); + fixture.detectChanges(); + + tick(500); + + expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeFalsy(); + })); + + it('should be able to add the backdrop using hasBackdrop option', fakeAsync(() => { + const fixture = createComponent(SimpleAutocomplete, [ + { + provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS, + useValue: {hasBackdrop: true}, + }, + ]); + fixture.detectChanges(); + fixture.componentInstance.trigger.openPanel(); + fixture.detectChanges(); + + tick(500); + + expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeTruthy(); + })); + }); + + describe('with hasBackdrop and backdropClass in options', () => { + it('should be able to configure custom backdrop class', fakeAsync(() => { + const fixture = createComponent(SimpleAutocomplete, [ + { + provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS, + useValue: {backdropClass: 'my-custom-backdrop-class', hasBackdrop: true}, + }, + ]); + fixture.detectChanges(); + fixture.componentInstance.trigger.openPanel(); + fixture.detectChanges(); + + tick(500); + + const cdkPanelElement = overlayContainerElement.querySelector('.cdk-overlay-backdrop'); + expect(cdkPanelElement?.classList).toContain('my-custom-backdrop-class'); + })); + }); + describe('misc', () => { it('should allow basic use without any forms directives', () => { expect(() => { diff --git a/src/material/autocomplete/autocomplete.ts b/src/material/autocomplete/autocomplete.ts index 5a59d5581a31..89993cdf0003 100644 --- a/src/material/autocomplete/autocomplete.ts +++ b/src/material/autocomplete/autocomplete.ts @@ -70,6 +70,12 @@ export interface MatAutocompleteDefaultOptions { */ requireSelection?: boolean; + /** Class to be applied to the autocomplete's backdrop. */ + backdropClass?: string; + + /** Whether the autocomplete has a backdrop. */ + hasBackdrop?: boolean; + /** Class or list of classes to be applied to the autocomplete's overlay panel. */ overlayPanelClass?: string | string[]; @@ -97,6 +103,7 @@ export function MAT_AUTOCOMPLETE_DEFAULT_OPTIONS_FACTORY(): MatAutocompleteDefau autoSelectActiveOption: false, hideSingleSelectionIndicator: false, requireSelection: false, + hasBackdrop: false, }; }