I have the following code for opening and closing a slide menu for each row in the table. The <td>
is as shown below:
<td class="rm-release_table-cell" *ngIf="settings.actions">
<div>
<a id="release-action" href="javascript:void(0)" (click)="openAction($event)">
<i class="material-icons">more_vert</i>
</a>
<div class="rm-release_action-layout hidden" #actionSlide id="release-{{release[settings.columns[0].field]}}">
<div class="rm-release_action-container animate__animated" #actionContainer>
<div class="d-flex align-items-center justify-content-between rm-release_action-header">
<a class="rm-release_action-close" href="javascript:void(0)" (click)="closeAction($event)">
<i class="material-icons">close</i>
</a>
</div>
<div class="rm-release_action-item-layout">
<div class="rm-release_action-item-layout">
<ng-container *ngIf="release.permitted_actions;else actionMenu">
<ng-container *ngFor="let action of settings.actions">
<div *ngIf="release.permitted_actions.includes(action.action)" class="d-flex align-items-center rm-release_action-item" (click)="onAction(action.action, release)">
<i class="material-icons">{{action.icon}}</i>
<p>{{action.title}}</p>
</div>
</ng-container>
</ng-container>
<ng-template #actionMenu>
<ng-container *ngFor="let action of settings.actions">
<div class="d-flex align-items-center rm-release_action-item" (click)="onAction(action.action, release)">
<i class="material-icons">{{action.icon}}</i>
<p>{{action.title}}</p>
</div>
</ng-container>
</ng-template>
</div>
</div>
</div>
</div>
</div>
</td>
and the code in the component file is as shown below :
/**
*
* @param event
*/
public openAction(event) {
const parent = this.renderer.parentNode(event.target);
const containerRef = this.renderer.nextSibling(parent);
//second parent
let elements = this.elem.nativeElement.querySelectorAll('.rm-release_action-layout');
_.forEach(elements, function (element) {
if (element.id != containerRef.id) {
element.classList.add('hidden');
} else {
element.style.height = 'auto';
element.style.width = '12rem';
element.style.padding = '0.5rem'
}
// this.elem.nativeElement.classList.add('hidden');
// this.renderer.addClass(element, 'hidden');
});
//third parent
let parentElements = this.elem.nativeElement.querySelectorAll('.rm-release_action-container');
_.forEach(parentElements, function (parentElement) {
const parentNode = parentElement.parentNode;
if (parentNode.id == containerRef.id) {
parentNode.style.height = 'auto';
parentNode.style.width = '12rem';
parentNode.style.padding = '0.5rem';
}
});
//const containerRef = this.renderer.nextSibling(parent);
const containerChild = containerRef.children[0];
this.renderer.removeClass(containerRef, "hidden");
setTimeout(() => {
this.renderer.setStyle(containerRef, "height", "auto");
this.renderer.setStyle(containerRef, "width", "12rem");
this.renderer.setStyle(
containerRef,
"padding",
"0.5rem"
);
}, 100);
setTimeout(() => {
this.renderer.removeClass(containerChild, "hidden");
}, 600);
this.renderer.addClass(containerChild, 'animate__fadeIn');
}
/**
*
* @param event
*/
public closeAction(event) {
var parent = this.renderer.parentNode(event.target);
var firstParent = this.renderer.parentNode(parent);
var secondParent = this.renderer.parentNode(firstParent);
var thirdParent = this.renderer.parentNode(secondParent);
setTimeout(() => {
this.renderer.addClass(secondParent, 'hidden');
this.renderer.setStyle(thirdParent, 'height', '0rem');
this.renderer.setStyle(thirdParent, 'width', '0rem');
this.renderer.setStyle(thirdParent, 'padding', '0rem');
}, 50);
setTimeout(() => {
this.renderer.addClass(thirdParent, 'hidden');
}, 500);
}
Now this is showing the action menu and it is closing when I click on the close icon. I need to close this action menu when I click anywhere outside the opened element. How this can be done ? Thanks in advance
Add class to DOM nodes of popup & outside of popup. Then just check if click event triggered on DOM part inside of popup or outside.
file.ts
file.html
Example
https://stackblitz.com/edit/angular-hostlistener-clicked-inside-outside