diff --git a/cypress/integration/modals_page_spec.ts b/cypress/integration/modals_page_spec.ts index e6fc936d61..635356ed1b 100644 --- a/cypress/integration/modals_page_spec.ts +++ b/cypress/integration/modals_page_spec.ts @@ -44,5 +44,11 @@ describe('Modals demo page test suite', () => { modals.isModalEnabled(modals.modalContainer, false); modals.isBackdropExist(false); }); + + it('when user starts to click on body then release click on backdrop then the modal is not closed', () => { + modals.clickByText(templateDemo, btnText); + modals.startClickOnModalReleaseOnBackdrop(modals.modalContainer); + modals.isModalVisible(modals.modalContainerVisible, true); + }); }); }); diff --git a/cypress/support/modals.po.ts b/cypress/support/modals.po.ts index 7c6a42fb43..ff1c1e1501 100644 --- a/cypress/support/modals.po.ts +++ b/cypress/support/modals.po.ts @@ -6,6 +6,7 @@ export class ModalsPo extends BaseComponent { ghLinkToComponent = 'https://github.com/valor-software/ngx-bootstrap/tree/development/src/modal'; modalContainer = 'modal-container'; + modalContainerVisible = 'modal-container.show'; modalContent = '.modal-content'; modalDialog = '.modal-dialog'; modalBody = '.modal-body'; @@ -77,6 +78,14 @@ export class ModalsPo extends BaseComponent { cy.get(`${baseSelector} .modal`).click(); } + startClickOnModalReleaseOnBackdrop(baseSelector: string) { + cy.get(`${baseSelector} .modal-content`) + .trigger('mousedown') + .wait(100) + .get(this.modalContainer) + .trigger('mouseup'); + } + checkElementsQuantity(elementsSelector: string, expectedQuantity: number) { cy.get(elementsSelector).should('have.length', expectedQuantity); } diff --git a/src/modal/modal-container.component.ts b/src/modal/modal-container.component.ts index 40cba5ae91..eeeedbbc51 100644 --- a/src/modal/modal-container.component.ts +++ b/src/modal/modal-container.component.ts @@ -38,6 +38,7 @@ export class ModalContainerComponent implements OnInit, OnDestroy { isAnimated: boolean; bsModalService: BsModalService; private isModalHiding = false; + private clickStartedInContent = false; constructor(options: ModalOptions, protected _element: ElementRef, @@ -76,13 +77,21 @@ export class ModalContainerComponent implements OnInit, OnDestroy { } } - @HostListener('click', ['$event']) - onClick(event: MouseEvent): void { + @HostListener('mousedown', ['$event']) + onClickStarted(event: MouseEvent): void { + this.clickStartedInContent = event.target !== this._element.nativeElement; + } + + @HostListener('mouseup', ['$event']) + onClickStop(event: MouseEvent): void { + const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent; if ( this.config.ignoreBackdropClick || this.config.backdrop === 'static' || - event.target !== this._element.nativeElement + !clickedInBackdrop ) { + this.clickStartedInContent = false; + return; } this.bsModalService.setDismissReason(DISMISS_REASONS.BACKRDOP); diff --git a/src/modal/modal.directive.ts b/src/modal/modal.directive.ts index 6056b2c2aa..0213ea209e 100644 --- a/src/modal/modal.directive.ts +++ b/src/modal/modal.directive.ts @@ -78,6 +78,7 @@ export class ModalDirective implements OnDestroy, OnInit { private _backdrop: ComponentLoader; private isNested = false; + private clickStartedInContent = false; constructor(private _element: ElementRef, _viewContainerRef: ViewContainerRef, @@ -90,13 +91,21 @@ export class ModalDirective implements OnDestroy, OnInit { ); } - @HostListener('click', ['$event']) - onClick(event: MouseEvent): void { + @HostListener('mousedown', ['$event']) + onClickStarted(event: MouseEvent): void { + this.clickStartedInContent = event.target !== this._element.nativeElement; + } + + @HostListener('mouseup', ['$event']) + onClickStop(event: MouseEvent): void { + const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent; if ( this.config.ignoreBackdropClick || this.config.backdrop === 'static' || - event.target !== this._element.nativeElement + !clickedInBackdrop ) { + this.clickStartedInContent = false; + return; } this.dismissReason = DISMISS_REASONS.BACKRDOP;