tree-view.html
<div *ngFor="let item of nodes; let i=index" class="parent" [id]="item.name" appTreeView>
{{item.name}}
<div class="child" *ngIf="item.child">
<app-tree-view [nodes]="item.child"></app-tree-view> // recursive call
</div>
</div>
treeview.ts
this.data=[
{
name:"level 1",
child:[
{
name:"level 1.1",
}
]
},
{
name:"level 2",
child:[
{
name:"level 2.1",
child:[
{
name:"level 2.1.1"
}
]
}
]
}
]
directive.ts
import { Directive, HostListener,Renderer2 } from '@angular/core';
@Directive({
selector: '[appTreeView]',
})
export class TreeViewDirective {
constructor(private render:Renderer2) { }
@HostListener('click',['$event'])
check(event){
console.log(event.target.id);
const avalclass:string=event.target.classList.value;
if(avalclass.includes('expand')){
this.render.removeClass(event.target,'expand');
}else{
this.render.addClass(event.target,'expand');
}
}
}
Output
If I click level 2 expand sub menu level 2.1 console print one time
then i click level 2.1 expand sub menu 2.1.1 console print two times
Why console print multiple times. what is my mistakes
Console prints multiple times the same because of you are using recursion to call a parent and his descendants. You are binding a click event multiple times depending on what level is the element where you're clicking on. If you are aware of the flow of your code:
I've prepared a demo with the code that you put in your question. You can see in the console who is calling the event and who is the host element each time.
https://stackblitz.com/edit/angular-recursion-directives?file=src/app/tree-view.directive.ts
You could solve that adding a flag to your directive and checking it in your check function:
if (this.isFired) {
return;
}
this.isFired = true;
Or comparing the current host element and the element that triggered the event:
if(this.el.nativeElement.id == event.target.id){
console.log("click on: " + event.target.id);
const avalclass: string = event.target.classList.value;
if (avalclass.includes("expand")) {
this.render.removeClass(event.target, "expand");
} else {
this.render.addClass(event.target, "expand");
}
}
}