diff --git a/projects/igniteui-angular/src/lib/services/overlay/overlay.spec.ts b/projects/igniteui-angular/src/lib/services/overlay/overlay.spec.ts index fb9a5c92c8d..a51de2a7024 100644 --- a/projects/igniteui-angular/src/lib/services/overlay/overlay.spec.ts +++ b/projects/igniteui-angular/src/lib/services/overlay/overlay.spec.ts @@ -727,6 +727,42 @@ describe('igxOverlay', () => { expect(overlayInstance.onOpening.emit).toHaveBeenCalledTimes(2); expect(overlayInstance.onOpened.emit).toHaveBeenCalledTimes(1); })); + + it('fix for #3673 - Should not close dropdown in dropdown', fakeAsync(() => { + const fix = TestBed.createComponent(EmptyPageComponent); + const button = fix.componentInstance.buttonElement; + const overlay = fix.componentInstance.overlay; + fix.detectChanges(); + + const overlaySettings: OverlaySettings = { + positionStrategy: new ConnectedPositioningStrategy(), + modal: false, + closeOnOutsideClick: true + }; + + overlaySettings.positionStrategy.settings.target = button.nativeElement; + + overlay.show(SimpleDynamicComponent, overlaySettings); + overlaySettings.positionStrategy.settings.horizontalStartPoint = HorizontalAlignment.Right; + overlay.show(SimpleDynamicComponent, overlaySettings); + fix.detectChanges(); + tick(); + + let overlayDiv: Element = document.getElementsByClassName(CLASS_OVERLAY_MAIN)[0]; + expect(overlayDiv).toBeDefined(); + expect(overlayDiv.children.length).toEqual(2); + expect(overlayDiv.children[0].localName).toEqual('div'); + expect(overlayDiv.children[1].localName).toEqual('div'); + + (overlay)._overlayInfos[0].elementRef.nativeElement.click(); + fix.detectChanges(); + tick(); + + overlayDiv = document.getElementsByClassName(CLASS_OVERLAY_MAIN)[0]; + expect(overlayDiv).toBeDefined(); + expect(overlayDiv.children.length).toEqual(1); + expect(overlayDiv.children[0].localName).toEqual('div'); + })); }); describe('Unit Tests - Scroll Strategies: ', () => { @@ -3379,12 +3415,15 @@ export class SimpleDynamicWithDirectiveComponent { } @Component({ - template: `` + template: ` + + ` }) export class EmptyPageComponent { constructor(@Inject(IgxOverlayService) public overlay: IgxOverlayService) { } @ViewChild('button') buttonElement: ElementRef; + @ViewChild('div') divElement: ElementRef; click(event) { this.overlay.show(SimpleDynamicComponent); diff --git a/projects/igniteui-angular/src/lib/services/overlay/overlay.ts b/projects/igniteui-angular/src/lib/services/overlay/overlay.ts index 7198185eaf8..bed99bd5d7d 100644 --- a/projects/igniteui-angular/src/lib/services/overlay/overlay.ts +++ b/projects/igniteui-angular/src/lib/services/overlay/overlay.ts @@ -520,6 +520,12 @@ export class IgxOverlayService implements OnDestroy { } private documentClicked = (ev: Event) => { + // if we get to modal overlay just return - we should not close anything under it + // if we get to non-modal overlay do the next: + // 1. Check it has close on outside click. If not go on to next overlay; + // 2. If true check if click is on the element. If it is on the element we have closed + // already all previous non-modal with close on outside click elements, so we return. If + // not close the overlay and check next for (let i = this._overlayInfos.length; i--;) { const info = this._overlayInfos[i]; if (info.settings.modal) { @@ -528,7 +534,8 @@ export class IgxOverlayService implements OnDestroy { if (info.settings.closeOnOutsideClick) { if (!info.elementRef.nativeElement.contains(ev.target)) { this.hide(info.id); - // TODO: should we return here too and not closing all no-modal overlays? + } else { + return; } } } diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts b/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts index d3eb385534c..a4f6787a0c7 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts @@ -335,7 +335,7 @@ export class IgxAmPmItemDirective { } /** - * @hidden + * This directive should be used to mark which ng-template will be used from IgxTimePicker when re-templating its input group. */ @Directive({ selector: '[igxTimePickerTemplate]'