diff --git a/src/material/select/select.html b/src/material/select/select.html
index 6eaecee7f5c3..ba6439f3fe45 100644
--- a/src/material/select/select.html
+++ b/src/material/select/select.html
@@ -40,6 +40,7 @@
[cdkConnectedOverlayPositions]="_positions"
[cdkConnectedOverlayWidth]="_overlayWidth"
[cdkConnectedOverlayFlexibleDimensions]="true"
+ cdkConnectedOverlayUsePopover="inline"
(detach)="close()"
(backdropClick)="close()"
(overlayKeydown)="_handleOverlayKeydown($event)">
diff --git a/src/material/select/select.spec.ts b/src/material/select/select.spec.ts
index 45a24a15d45f..e58ee1e5bee7 100644
--- a/src/material/select/select.spec.ts
+++ b/src/material/select/select.spec.ts
@@ -76,7 +76,7 @@ import {
const DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL = 200;
describe('MatSelect', () => {
- let overlayContainerElement: HTMLElement;
+ const supportsPopover = 'showPopover' in document.body;
let dir: WritableSignal;
let scrolledSubject = new Subject();
@@ -94,10 +94,23 @@ describe('MatSelect', () => {
},
],
});
-
- overlayContainerElement = TestBed.inject(OverlayContainer).getContainerElement();
});
+ function getOverlayHost(fixture: ComponentFixture): HTMLElement | null {
+ return supportsPopover
+ ? fixture.nativeElement.querySelector('.cdk-overlay-popover')
+ : TestBed.inject(OverlayContainer)
+ .getContainerElement()
+ .querySelector('.cdk-overlay-connected-position-bounding-box');
+ }
+
+ function getBackdrop(fixture: ComponentFixture): HTMLElement | null {
+ const parent = supportsPopover
+ ? fixture.nativeElement
+ : TestBed.inject(OverlayContainer).getContainerElement();
+ return parent.querySelector('.cdk-overlay-backdrop');
+ }
+
describe('core', () => {
describe('accessibility', () => {
describe('for select', () => {
@@ -414,7 +427,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelectorAll('mat-option')[3] as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelectorAll('mat-option')[3] as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -769,7 +782,7 @@ describe('MatSelect', () => {
multiFixture.componentInstance.select.open();
multiFixture.detectChanges();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(multiFixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -982,7 +995,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll('mat-option');
+ const options = getOverlayHost(fixture)!.querySelectorAll('mat-option');
expect(host.getAttribute('aria-activedescendant'))
.withContext('Expected aria-activedescendant to match the active option.')
@@ -1004,7 +1017,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll('mat-option');
+ const options = getOverlayHost(fixture)!.querySelectorAll('mat-option');
expect(host.getAttribute('aria-activedescendant')).toBe(options[0].id);
@@ -1028,7 +1041,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll('mat-option');
+ const options = getOverlayHost(fixture)!.querySelectorAll('mat-option');
expect(host.getAttribute('aria-activedescendant')).toBe(options[0].id);
@@ -1055,7 +1068,7 @@ describe('MatSelect', () => {
select.blur();
expect(document.activeElement).not.toBe(select, 'Expected trigger not to be focused.');
- const option = overlayContainerElement.querySelector('mat-option')! as HTMLElement;
+ const option = getOverlayHost(multiFixture)!.querySelector('mat-option')! as HTMLElement;
option.click();
multiFixture.detectChanges();
@@ -1154,7 +1167,9 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- options = Array.from(overlayContainerElement.querySelectorAll('mat-option'));
+ options = Array.from(
+ getOverlayHost(fixture)!.querySelectorAll('mat-option'),
+ );
});
it('should set the role of mat-option to option', fakeAsync(() => {
@@ -1202,7 +1217,9 @@ describe('MatSelect', () => {
trigger.click();
multiFixture.detectChanges();
- options = Array.from(overlayContainerElement.querySelectorAll('mat-option'));
+ options = Array.from(
+ getOverlayHost(multiFixture)!.querySelectorAll('mat-option'),
+ );
expect(
options.every(
@@ -1340,7 +1357,9 @@ describe('MatSelect', () => {
multiFixture.detectChanges();
flush();
- options = Array.from(overlayContainerElement.querySelectorAll('mat-option'));
+ options = Array.from(
+ getOverlayHost(multiFixture)!.querySelectorAll('mat-option'),
+ );
const pseudoCheckboxes = options
.map(option => option.querySelector('.mat-pseudo-checkbox.mat-pseudo-checkbox-full'))
.filter((x): x is HTMLElement => !!x);
@@ -1366,7 +1385,7 @@ describe('MatSelect', () => {
trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement;
trigger.click();
fixture.detectChanges();
- groups = overlayContainerElement.querySelectorAll(
+ groups = getOverlayHost(fixture)!.querySelectorAll(
'mat-optgroup',
) as NodeListOf;
});
@@ -1431,10 +1450,11 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
+ const overlay = getOverlayHost(fixture)!;
expect(fixture.componentInstance.select.panelOpen).toBe(true);
- expect(overlayContainerElement.textContent).toContain('Steak');
- expect(overlayContainerElement.textContent).toContain('Pizza');
- expect(overlayContainerElement.textContent).toContain('Tacos');
+ expect(overlay.textContent).toContain('Steak');
+ expect(overlay.textContent).toContain('Pizza');
+ expect(overlay.textContent).toContain('Tacos');
}));
it('should close the panel when an item is clicked', fakeAsync(() => {
@@ -1442,12 +1462,12 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
- expect(overlayContainerElement.textContent).toEqual('');
+ expect(getOverlayHost(fixture)!).toBeFalsy();
expect(fixture.componentInstance.select.panelOpen).toBe(false);
}));
@@ -1456,15 +1476,11 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const backdrop = overlayContainerElement.querySelector(
- '.cdk-overlay-backdrop',
- ) as HTMLElement;
-
- backdrop.click();
+ getBackdrop(fixture)!.click();
fixture.detectChanges();
flush();
- expect(overlayContainerElement.textContent).toEqual('');
+ expect(getOverlayHost(fixture)!).toBeFalsy();
expect(fixture.componentInstance.select.panelOpen).toBe(false);
}));
@@ -1475,7 +1491,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(pane.style.width).toBe('200px');
}));
@@ -1486,7 +1502,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement;
const initialWidth = parseInt(pane.style.width || '0');
expect(initialWidth).toBeGreaterThan(0);
@@ -1509,7 +1525,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(pane.style.width).toBe('42px');
}));
@@ -1522,7 +1538,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(pane.style.width).toBeFalsy();
}));
@@ -1535,7 +1551,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(pane.style.width).toBeFalsy();
}));
@@ -1590,7 +1606,7 @@ describe('MatSelect', () => {
expect(fixture.componentInstance.select.panelOpen).toBe(true);
- const panel = overlayContainerElement.querySelector('.mat-mdc-select-panel')!;
+ const panel = getOverlayHost(fixture)!.querySelector('.mat-mdc-select-panel')!;
dispatchKeyboardEvent(panel, 'keydown', TAB);
fixture.detectChanges();
flush();
@@ -1663,7 +1679,9 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const panel = overlayContainerElement.querySelector('.mat-mdc-select-panel') as HTMLElement;
+ const panel = getOverlayHost(fixture)!.querySelector(
+ '.mat-mdc-select-panel',
+ ) as HTMLElement;
expect(panel.classList).toContain('custom-one');
expect(panel.classList).toContain('custom-two');
@@ -1694,7 +1712,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelector('mat-option')!;
+ const option = getOverlayHost(fixture)!.querySelector('mat-option')!;
dispatchFakeEvent(option, 'mousedown');
dispatchFakeEvent(option, 'mouseup');
@@ -1711,7 +1729,7 @@ describe('MatSelect', () => {
trigger.click();
groupFixture.detectChanges();
- expect(document.querySelectorAll('.cdk-overlay-container mat-option').length)
+ expect(getOverlayHost(groupFixture)!.querySelectorAll('mat-option').length)
.withContext('Expected at least one option to be rendered.')
.toBeGreaterThan(0);
});
@@ -1804,7 +1822,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- let option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ let option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
@@ -1813,7 +1831,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
expect(option.classList).toContain('mdc-list-item--selected');
expect(fixture.componentInstance.options.first.selected).toBe(true);
@@ -1829,7 +1847,7 @@ describe('MatSelect', () => {
const optionInstances = fixture.componentInstance.options.toArray();
const optionNodes: NodeListOf =
- overlayContainerElement.querySelectorAll('mat-option');
+ getOverlayHost(fixture)!.querySelectorAll('mat-option');
optionInstances[1].select();
fixture.detectChanges();
@@ -1844,7 +1862,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- let options = overlayContainerElement.querySelectorAll(
+ let options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -1856,7 +1874,9 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- options = overlayContainerElement.querySelectorAll('mat-option') as NodeListOf;
+ options = getOverlayHost(fixture)!.querySelectorAll(
+ 'mat-option',
+ ) as NodeListOf;
expect(options[1].classList).not.toContain('mdc-list-item--selected');
expect(options[2].classList).not.toContain('mdc-list-item--selected');
@@ -1873,7 +1893,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- let options = overlayContainerElement.querySelectorAll(
+ let options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -1888,7 +1908,9 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- options = overlayContainerElement.querySelectorAll('mat-option') as NodeListOf;
+ options = getOverlayHost(fixture)!.querySelectorAll(
+ 'mat-option',
+ ) as NodeListOf;
expect(options[0].classList).not.toContain(
'mdc-list-item--selected',
@@ -1915,7 +1937,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- let firstOption = overlayContainerElement.querySelectorAll('mat-option')[0] as HTMLElement;
+ let firstOption = getOverlayHost(fixture)!.querySelectorAll('mat-option')[0] as HTMLElement;
firstOption.click();
fixture.detectChanges();
@@ -1939,7 +1961,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
@@ -1974,7 +1996,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
options[8].click();
@@ -2018,7 +2040,7 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
options[2].click();
@@ -2037,7 +2059,7 @@ describe('MatSelect', () => {
groupFixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement.click();
groupFixture.detectChanges();
- const disabledGroup = overlayContainerElement.querySelectorAll('mat-optgroup')[1];
+ const disabledGroup = getOverlayHost(groupFixture)!.querySelectorAll('mat-optgroup')[1];
const options = disabledGroup.querySelectorAll('mat-option');
(options[0] as HTMLElement).click();
@@ -2059,7 +2081,7 @@ describe('MatSelect', () => {
const spy = jasmine.createSpy('option selection spy');
const subscription = fixture.componentInstance.select.optionSelectionChanges.subscribe(spy);
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
@@ -2088,7 +2110,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
@@ -2106,7 +2128,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
@@ -2169,7 +2191,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
expect(options[1].classList)
@@ -2193,7 +2215,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
expect(options[1].classList)
@@ -2210,7 +2232,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
@@ -2240,7 +2262,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
expect(options[1].classList).not.toContain(
@@ -2269,7 +2291,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
expect(options[1].classList).not.toContain(
@@ -2292,10 +2314,7 @@ describe('MatSelect', () => {
.withContext(`Expected the control to stay untouched when menu opened.`)
.toEqual(false);
- const backdrop = overlayContainerElement.querySelector(
- '.cdk-overlay-backdrop',
- ) as HTMLElement;
- backdrop.click();
+ getBackdrop(fixture)!.click();
dispatchFakeEvent(trigger, 'blur');
fixture.detectChanges();
flush();
@@ -2350,7 +2369,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
flush();
@@ -2417,9 +2436,9 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- expect(overlayContainerElement.textContent)
+ expect(getOverlayHost(fixture)?.querySelector('.mat-mdc-select-panel'))
.withContext(`Expected select panel to stay closed.`)
- .toEqual('');
+ .toBeFalsy();
expect(fixture.componentInstance.select.panelOpen)
.withContext(`Expected select panelOpen property to stay false.`)
.toBe(false);
@@ -2434,7 +2453,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- expect(overlayContainerElement.textContent)
+ expect(getOverlayHost(fixture)?.querySelector('.mat-mdc-select-panel')?.textContent)
.withContext(`Expected select panel to open normally on re-enabled control`)
.toContain('Steak');
expect(fixture.componentInstance.select.panelOpen)
@@ -2478,7 +2497,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
host = fixture.debugElement.query(By.css('mat-select'))!.nativeElement;
- panel = overlayContainerElement.querySelector('.mat-mdc-select-panel')! as HTMLElement;
+ panel = getOverlayHost(fixture)!.querySelector('.mat-mdc-select-panel')! as HTMLElement;
}));
it('should not scroll to options that are completely in the view', () => {
@@ -2527,7 +2546,9 @@ describe('MatSelect', () => {
flush();
host = groupFixture.debugElement.query(By.css('mat-select'))!.nativeElement;
- panel = overlayContainerElement.querySelector('.mat-mdc-select-panel')! as HTMLElement;
+ panel = getOverlayHost(groupFixture)!.querySelector(
+ '.mat-mdc-select-panel',
+ )! as HTMLElement;
for (let i = 0; i < 8; i++) {
dispatchKeyboardEvent(host, 'keydown', DOWN_ARROW);
@@ -2649,7 +2670,9 @@ describe('MatSelect', () => {
flush();
host = groupFixture.debugElement.query(By.css('mat-select'))!.nativeElement;
- panel = overlayContainerElement.querySelector('.mat-mdc-select-panel')! as HTMLElement;
+ panel = getOverlayHost(groupFixture)!.querySelector(
+ '.mat-mdc-select-panel',
+ )! as HTMLElement;
for (let i = 0; i < 5; i++) {
dispatchKeyboardEvent(host, 'keydown', DOWN_ARROW);
@@ -2703,7 +2726,7 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
expect(fixture.componentInstance.changeListener).toHaveBeenCalled();
});
@@ -2712,7 +2735,7 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
option.click();
@@ -2750,9 +2773,9 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- expect(overlayContainerElement.textContent)
+ expect(getOverlayHost(fixture)?.querySelector('.mat-mdc-select-panel'))
.withContext(`Expected select panel to stay closed.`)
- .toEqual('');
+ .toBeFalsy();
expect(fixture.componentInstance.select.panelOpen)
.withContext(`Expected select panelOpen property to stay false.`)
.toBe(false);
@@ -2771,7 +2794,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- expect(overlayContainerElement.textContent)
+ expect(getOverlayHost(fixture)?.querySelector('.mat-mdc-select-panel')?.textContent)
.withContext(`Expected select panel to open normally on re-enabled control`)
.toContain('Steak');
expect(fixture.componentInstance.select.panelOpen)
@@ -2802,13 +2825,13 @@ describe('MatSelect', () => {
.withContext(`Expected trigger to be populated by the control's initial value.`)
.toContain('Pizza');
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)!.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(pane.style.width).toEqual('300px');
expect(fixture.componentInstance.select.panelOpen).toBe(true);
- expect(overlayContainerElement.textContent).toContain('Steak');
- expect(overlayContainerElement.textContent).toContain('Pizza');
- expect(overlayContainerElement.textContent).toContain('Tacos');
+ expect(pane.textContent).toContain('Steak');
+ expect(pane.textContent).toContain('Pizza');
+ expect(pane.textContent).toContain('Tacos');
}));
});
@@ -2826,7 +2849,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- options = overlayContainerElement.querySelectorAll('mat-option') as NodeListOf;
+ options = getOverlayHost(fixture)!.querySelectorAll('mat-option') as NodeListOf;
}));
it('should set the option id', fakeAsync(() => {
@@ -2837,10 +2860,7 @@ describe('MatSelect', () => {
.toContain('mat-option');
expect(options[0].id).not.toEqual(options[1].id, `Expected option IDs to be unique.`);
- const backdrop = overlayContainerElement.querySelector(
- '.cdk-overlay-backdrop',
- ) as HTMLElement;
- backdrop.click();
+ getBackdrop(fixture)!.click();
fixture.detectChanges();
flush();
@@ -2848,7 +2868,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- options = overlayContainerElement.querySelectorAll('mat-option') as NodeListOf;
+ options = getOverlayHost(fixture)!.querySelectorAll('mat-option') as NodeListOf;
expect(options[0].id)
.withContext(`Expected option ID to have the correct prefix.`)
.toContain('mat-option');
@@ -2963,7 +2983,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)!.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(pane.style.width).toBe('300px');
}));
});
@@ -2979,7 +2999,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
+ const pane = getOverlayHost(fixture)!.querySelector('.cdk-overlay-pane') as HTMLElement;
expect(parseInt(pane.style.width as string)).toBeGreaterThan(0);
}));
});
@@ -3000,7 +3020,7 @@ describe('MatSelect', () => {
fixture.componentInstance.select.open();
fixture.detectChanges();
- const panel = overlayContainerElement.querySelector('.mat-mdc-select-panel')! as HTMLElement;
+ const panel = getOverlayHost(fixture)!.querySelector('.mat-mdc-select-panel')! as HTMLElement;
expect(panel.classList).toContain('mat-warn');
});
});
@@ -3329,7 +3349,7 @@ describe('MatSelect', () => {
expect(fixture.componentInstance.options.first.selected)
.withContext('Expected first option to be selected')
.toBe(true);
- expect(overlayContainerElement.querySelectorAll('mat-option')[0].classList)
+ expect(getOverlayHost(fixture)!.querySelectorAll('mat-option')[0].classList)
.withContext('Expected first option to be selected')
.toContain('mdc-list-item--selected');
}));
@@ -3409,7 +3429,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- options = overlayContainerElement.querySelectorAll('mat-option') as NodeListOf;
+ options = getOverlayHost(fixture)!.querySelectorAll('mat-option') as NodeListOf;
options[0].click();
fixture.detectChanges();
flush();
@@ -3504,7 +3524,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- options = overlayContainerElement.querySelectorAll('mat-option') as NodeListOf;
+ options = getOverlayHost(fixture)!.querySelectorAll('mat-option') as NodeListOf;
options[0].click();
fixture.detectChanges();
flush();
@@ -3590,7 +3610,7 @@ describe('MatSelect', () => {
trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement;
trigger.click();
fixture.detectChanges();
- options = Array.from(overlayContainerElement.querySelectorAll('mat-option'));
+ options = Array.from(getOverlayHost(fixture)!.querySelectorAll('mat-option'));
});
it('should set the select value', fakeAsync(() => {
@@ -3648,7 +3668,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -3660,7 +3680,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelectorAll('mat-option')[2] as HTMLElement).click();
+ (getOverlayHost(fixture)!.querySelectorAll('mat-option')[2] as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -3684,7 +3704,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelectorAll('mat-option')[2];
+ const option = getOverlayHost(fixture)!.querySelectorAll('mat-option')[2];
expect(option.classList).toContain('mdc-list-item--selected');
expect(fixture.componentInstance.select.value).toBe('sandwich-2');
@@ -3702,7 +3722,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -3732,7 +3752,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const option = overlayContainerElement.querySelectorAll('mat-option')[1];
+ const option = getOverlayHost(fixture)!.querySelectorAll('mat-option')[1];
expect(option.classList).toContain('mdc-list-item--selected');
expect(fixture.componentInstance.select.value).toBe('pizza-1');
@@ -3750,7 +3770,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -3784,7 +3804,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -3806,7 +3826,7 @@ describe('MatSelect', () => {
expect(document.activeElement).withContext('Expected trigger to be focused.').toBe(select);
select.blur(); // Blur manually since the programmatic click might not do it.
- (overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement).click();
+ getBackdrop(fixture)!.click();
fixture.detectChanges();
flush();
@@ -3827,7 +3847,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -3931,7 +3951,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -3957,7 +3977,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -3967,7 +3987,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- (overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
+ (getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement).click();
fixture.detectChanges();
flush();
@@ -4031,7 +4051,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const panel = overlayContainerElement.querySelector('.cdk-overlay-pane')!;
+ const panel = getOverlayHost(fixture)!.querySelector('.cdk-overlay-pane')!;
const paneRect = panel.getBoundingClientRect();
const formFieldWrapperRect = formFieldWrapper.getBoundingClientRect();
@@ -4049,7 +4069,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const panel = overlayContainerElement.querySelector('.cdk-overlay-pane')!;
+ const panel = getOverlayHost(fixture)!.querySelector('.cdk-overlay-pane')!;
const paneRect = panel.getBoundingClientRect();
const formFieldWrapperRect = formFieldWrapper.getBoundingClientRect();
@@ -4076,7 +4096,7 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4092,7 +4112,7 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const option = overlayContainerElement.querySelector('mat-option') as HTMLElement;
+ const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement;
option.click();
fixture.detectChanges();
@@ -4110,7 +4130,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4132,7 +4152,7 @@ describe('MatSelect', () => {
testInstance.control.setValue(['steak-0', 'eggs-5']);
fixture.detectChanges();
- const optionNodes = overlayContainerElement.querySelectorAll(
+ const optionNodes = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4149,7 +4169,7 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4171,7 +4191,7 @@ describe('MatSelect', () => {
expect(testInstance.select.panelOpen).toBe(true);
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4187,7 +4207,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4206,7 +4226,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4230,7 +4250,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
flush();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4303,7 +4323,7 @@ describe('MatSelect', () => {
expect(fixture.componentInstance.select._keyManager.activeItemIndex).toBe(0);
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4325,7 +4345,7 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const options = overlayContainerElement.querySelectorAll(
+ const options = getOverlayHost(fixture)!.querySelectorAll(
'mat-option',
) as NodeListOf;
@@ -4479,7 +4499,9 @@ describe('MatSelect', () => {
trigger.click();
fixture.detectChanges();
- const optionNodes = Array.from(overlayContainerElement.querySelectorAll('mat-option'));
+ const optionNodes = Array.from(
+ getOverlayHost(fixture)!.querySelectorAll('mat-option'),
+ );
const optionInstances = testInstance.options.toArray();
expect(optionNodes.map(node => node.classList.contains('mdc-list-item--selected'))).toEqual([
@@ -4508,7 +4530,7 @@ describe('MatSelect', () => {
fixture.detectChanges();
const optionNodes = Array.from(
- overlayContainerElement.querySelectorAll('mat-option'),
+ getOverlayHost(fixture)!.querySelectorAll('mat-option'),
);
const optionInstances = testInstance.options.toArray();
diff --git a/src/material/select/select.ts b/src/material/select/select.ts
index 80bfea9f75a0..a80bed47b3c9 100644
--- a/src/material/select/select.ts
+++ b/src/material/select/select.ts
@@ -1476,13 +1476,23 @@ export class MatSelect
* @docs-private
*/
onContainerClick(event: MouseEvent) {
- const target = _getEventTarget(event) as Node | null;
- const overlayHost = this._overlayDir.overlayRef?.hostElement;
+ const target = _getEventTarget(event) as HTMLElement | null;
- if (!target || !overlayHost || !overlayHost.contains(target)) {
- this.focus();
- this.open();
+ // Since the overlay is inside the form field, this handler can fire for interactions
+ // with the container. Note that while it's redundant to select both for the popover
+ // and select panel, we need to do it because it tests the clicks can occur after
+ // the panel was detached from the popover.
+ if (
+ target &&
+ (target.tagName === 'MAT-OPTION' ||
+ target.classList.contains('cdk-overlay-backdrop') ||
+ target.closest('.mat-mdc-select-panel'))
+ ) {
+ return;
}
+
+ this.focus();
+ this.open();
}
/**