Skip to content

Commit 8208594

Browse files
authored
Merge pull request #8651 from IgniteUI/mvenkov/close-overlay-in-shadow-dom-10.2
Close on outside click when in shadow DOM - 10.2.x
2 parents 3989e10 + 5d100ab commit 8208594

File tree

2 files changed

+75
-20
lines changed

2 files changed

+75
-20
lines changed

projects/igniteui-angular/src/lib/services/overlay/overlay.spec.ts

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
ViewChild,
77
HostBinding,
88
ApplicationRef,
9-
ComponentRef
9+
ComponentRef,
10+
ViewEncapsulation
1011
} from '@angular/core';
1112
import { TestBed, fakeAsync, tick, async, inject } from '@angular/core/testing';
1213
import { BrowserModule, By } from '@angular/platform-browser';
@@ -177,9 +178,9 @@ function formatString(inputString: string, formatters: any[]) {
177178

178179
describe('igxOverlay', () => {
179180
const formatters = [
180-
{pattern: /:\s/g, replacement: ':'},
181-
{pattern: /red;/, replacement: 'red'}
182-
];
181+
{ pattern: /:\s/g, replacement: ':' },
182+
{ pattern: /red;/, replacement: 'red' }
183+
];
183184
beforeEach(async(() => {
184185
UIInteractions.clearOverlay();
185186
}));
@@ -825,7 +826,7 @@ describe('igxOverlay', () => {
825826
fix.detectChanges();
826827

827828
const overlaySettings: OverlaySettings = {
828-
target : button.nativeElement,
829+
target: button.nativeElement,
829830
positionStrategy: new ConnectedPositioningStrategy(),
830831
modal: false,
831832
closeOnOutsideClick: true
@@ -997,6 +998,46 @@ describe('igxOverlay', () => {
997998
overlayDiv = document.getElementsByClassName(CLASS_OVERLAY_MAIN)[0];
998999
expect(overlayDiv).toBeUndefined();
9991000
}));
1001+
1002+
it('should correctly handle close on outside click in shadow DOM', fakeAsync(() => {
1003+
const fix = TestBed.createComponent(EmptyPageInShadowDomComponent);
1004+
const button = fix.componentInstance.buttonElement;
1005+
const outlet = fix.componentInstance.outletElement;
1006+
const overlay = fix.componentInstance.overlay;
1007+
fix.detectChanges();
1008+
1009+
const overlaySettings: OverlaySettings = {
1010+
modal: false,
1011+
closeOnOutsideClick: true,
1012+
positionStrategy: new ConnectedPositioningStrategy(),
1013+
target: button.nativeElement,
1014+
outlet: outlet
1015+
};
1016+
1017+
overlay.show(overlay.attach(SimpleDynamicComponent), overlaySettings);
1018+
tick();
1019+
fix.detectChanges();
1020+
1021+
let overlayDiv: Element = outlet.nativeElement.getElementsByTagName('component')[0];
1022+
expect(overlayDiv).toBeDefined();
1023+
1024+
const toggledDiv = overlayDiv.children[0];
1025+
(toggledDiv as any).click();
1026+
1027+
tick();
1028+
fix.detectChanges();
1029+
1030+
overlayDiv = outlet.nativeElement.getElementsByTagName('component')[0];
1031+
expect(overlayDiv).toBeDefined();
1032+
1033+
document.body.click();
1034+
1035+
tick();
1036+
fix.detectChanges();
1037+
1038+
overlayDiv = outlet.nativeElement.getElementsByTagName('component')[0];
1039+
expect(overlayDiv).toBeUndefined();
1040+
}));
10001041
});
10011042

10021043
describe('Unit Tests - Scroll Strategies: ', () => {
@@ -1453,20 +1494,20 @@ describe('igxOverlay', () => {
14531494

14541495
it(`Should use StartPoint:Left/Bottom, Direction Right/Bottom and openAnimation: scaleInVerTop,
14551496
closeAnimation: scaleOutVerTop as default options when using a ConnectedPositioningStrategy without passing options.`, () => {
1456-
const strategy = new ConnectedPositioningStrategy();
1497+
const strategy = new ConnectedPositioningStrategy();
14571498

1458-
const expectedDefaults = {
1459-
horizontalDirection: HorizontalAlignment.Right,
1460-
verticalDirection: VerticalAlignment.Bottom,
1461-
horizontalStartPoint: HorizontalAlignment.Left,
1462-
verticalStartPoint: VerticalAlignment.Bottom,
1463-
openAnimation: scaleInVerTop,
1464-
closeAnimation: scaleOutVerTop,
1465-
minSize: { width: 0, height: 0 }
1466-
};
1499+
const expectedDefaults = {
1500+
horizontalDirection: HorizontalAlignment.Right,
1501+
verticalDirection: VerticalAlignment.Bottom,
1502+
horizontalStartPoint: HorizontalAlignment.Left,
1503+
verticalStartPoint: VerticalAlignment.Bottom,
1504+
openAnimation: scaleInVerTop,
1505+
closeAnimation: scaleOutVerTop,
1506+
minSize: { width: 0, height: 0 }
1507+
};
14671508

1468-
expect(strategy.settings).toEqual(expectedDefaults);
1469-
});
1509+
expect(strategy.settings).toEqual(expectedDefaults);
1510+
});
14701511

14711512
// adding more than one component to show in igx-overlay:
14721513
it('Should render the component exactly on top of the previous one when adding a new instance with default settings.', () => {
@@ -3925,6 +3966,20 @@ export class EmptyPageComponent {
39253966
}
39263967
}
39273968

3969+
@Component({
3970+
template: `
3971+
<button #button>Show Overlay</button>
3972+
<div igxOverlayOutlet #outlet></div>
3973+
`,
3974+
encapsulation: ViewEncapsulation.ShadowDom
3975+
})
3976+
export class EmptyPageInShadowDomComponent {
3977+
constructor(@Inject(IgxOverlayService) public overlay: IgxOverlayService) { }
3978+
3979+
@ViewChild('button', { static: true }) buttonElement: ElementRef;
3980+
@ViewChild('outlet', { static: true }) outletElement: ElementRef;
3981+
}
3982+
39283983
@Component({
39293984
template: `<button #button (click)='click($event)'>Show Overlay</button>`,
39303985
styles: [`button {
@@ -4012,7 +4067,6 @@ export class TwoButtonsComponent {
40124067
ev.stopPropagation();
40134068
}
40144069
}
4015-
40164070
@Component({
40174071
template: `
40184072
<div style="width: 420px; height: 280px;">
@@ -4112,6 +4166,7 @@ export class FlexContainerComponent {
41124166
const DYNAMIC_COMPONENTS = [
41134167
EmptyPageComponent,
41144168
SimpleRefComponent,
4169+
EmptyPageInShadowDomComponent,
41154170
SimpleDynamicComponent,
41164171
SimpleBigSizeComponent,
41174172
DownRightButtonComponent,

projects/igniteui-angular/src/lib/services/overlay/overlay.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ export class IgxOverlayService implements OnDestroy {
609609

610610
private getOverlayElement(info: OverlayInfo): HTMLElement {
611611
if (info.settings.outlet) {
612-
return info.settings.outlet.nativeElement;
612+
return info.settings.outlet.nativeElement || info.settings.outlet;
613613
}
614614
if (!this._overlayElement) {
615615
this._overlayElement = this._document.createElement('div');
@@ -810,7 +810,7 @@ export class IgxOverlayService implements OnDestroy {
810810
return;
811811
}
812812
if (info.settings.closeOnOutsideClick) {
813-
const target = ev.target;
813+
const target = ev.composed ? ev.composedPath()[0] : ev.target;
814814
const overlayElement = info.elementRef.nativeElement;
815815
// check if the click is on the overlay element or on an element from the exclusion list, and if so do not close the overlay
816816
const excludeElements = info.settings.excludeFromOutsideClick ?

0 commit comments

Comments
 (0)