Skip to content

Commit

Permalink
fix(modal): change the mouse event to dismiss a modal on backdrop cli…
Browse files Browse the repository at this point in the history
…ck (#5326)

* fix(modal): change the mouse event to dismiss a modal on backdrop click

Because of the use of a 'click' event to trigger the dismissal of a modal, the target of the event doesn't take into account an eventual movement of the mouse before releasing click (for ex. selection of text), which can lead to unwanted dismissal of the modal.

Closes: #5264

* fix(modal): change the mouse event to dismiss a modal from a directive

Because of the use of a 'click' event to trigger the dismissal of a modal, the target of the event doesn't take into account an eventual movement of the mouse before releasing click (for ex. selection of text), which can lead to unwanted dismissal of the modal.
  • Loading branch information
florenthobein authored and daniloff200 committed Jan 20, 2020
1 parent 4c92bd1 commit 74f752f
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
6 changes: 6 additions & 0 deletions cypress/integration/modals_page_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
});
9 changes: 9 additions & 0 deletions cypress/support/modals.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);
}
Expand Down
15 changes: 12 additions & 3 deletions src/modal/modal-container.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 12 additions & 3 deletions src/modal/modal.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class ModalDirective implements OnDestroy, OnInit {
private _backdrop: ComponentLoader<ModalBackdropComponent>;

private isNested = false;
private clickStartedInContent = false;

constructor(private _element: ElementRef,
_viewContainerRef: ViewContainerRef,
Expand All @@ -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;
Expand Down

0 comments on commit 74f752f

Please sign in to comment.