Home > Enterprise >  Angular modal is closing when clicking at the backdrop and at the content
Angular modal is closing when clicking at the backdrop and at the content

Time:02-28

I have created a small Angular component called Modal to use it as a modal on my app. The modal opens when clicking on a button on the page and should close when clicking on the backdrop or a cancel button.

Now is opening when clicking on the button on the page (good) and closing when clicking on the backdrop (good) my issue is that is closing when I click on the content (bad).

To manage when the modal is open or close I've defined a variable on the page controller that starts at false and when clicking on the button switches to true and shows the modal. When clicking on the backdrop the same function switches back the variable to false.

This is my board-page.component.ts:

export class BoardPageComponent implements OnInit {
  constructor() {}

  ngOnInit(): void {}

  isModalShown: boolean = false;

  newTask() {
    console.log(`Click Modal!`);
    this.isModalShown ? this.isModalShown = false : this.isModalShown = true;
  }
}

This is the board-page.component.html:

<app-modal *ngIf="isModalShown" (close)="newTask()">
  <h1>Modal Content</h1>
</app-modal> 

And this is the modal component modal.component.ts:

export class ModalComponent implements OnInit {
  @Output() close = new EventEmitter();

  constructor() {}

  ngOnInit(): void {
  }

  onClose() {
    this.close.emit();
  }
}

And the modal.component.html

<div  (click)="onClose()">
  <div  id='modal'>
    <ng-content></ng-content>
  </div>
</div>

I've placed the click event on the backdrop, but seems that when clicking on the content the click event fires thou the z-index is higher. When the click events are fired emits to the function in the parent component that updates the isModalShown value.

And the styles that make the backdrop and content effect:

.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  z-index: 20;
  background-color: rgba(0, 0, 0, 0.75);
}

.modal-content {
  position: fixed;
  top: 15vh;
  left: 5%;
  width: 90%;
  background-color: white;
  padding: 1rem;
  border-radius: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  z-index: 30;
  animation: slide-down 300ms ease-out forwards;

  pointer-events: none;
}

@media (min-width: 768px) {
  .modal-content {
    width: 40rem;
    left: calc(50% - 20rem);
  }
}

@keyframes slide-down {
  from {
    opacity: 0;
    transform: translateY(-3rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

I guess I should disable the click events on the content? I've tried with this:

document.getElementById('modal').addEventListener('click', (event) => {  
  event.preventDefault();  
});

But didn't work.

I did not find a lot of examples to do this modal without 3rd party libraries.

Edit: I also tried with a custom directive like this post: Stop mouse event propagation but didn't work.

CodePudding user response:

There is two things you should do:

  1. You should prevent propagation of events from content part like below
<div  (click)="onClose()">
  <div  (click)="$event.stopPropagation()" id="modalmodal">
    <ng-content></ng-content>
  </div>
</div>
  1. You should delete from your styles pointer-events: none for .modal-content, that's why events are not registered inside you content part and you are just clicking backdrop div in this way.
.modal-content {
  position: fixed;
  top: 15vh;
  left: 5%;
  width: 90%;
  background-color: white;
  padding: 1rem;
  border-radius: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  z-index: 30;
  animation: slide-down 300ms ease-out forwards;

  pointer-events: none; // remove this line
}
  • Related