You don't need to add all the data directly into your HTML. You can just create an array of objects which will make it perfect for a nested ngFor case.
Your data will look something like this
menus: any[] = [{
item: 'Item 1', submenus: [
{ item: 'a', info: 'Info of a' },
{ item: 'b', info: 'Info of b' },
{ item: 'c', info: 'Info of c' }
]
}, {
item: 'Item 2', submenus: [
{ item: 'd', info: 'Info of d' },
{ item: 'e', info: 'Info of e' },
{ item: 'f', info: 'Info of f' }
]
}, {
item: 'Item 3', submenus: [
{ item: 'g', info: 'Info of g' },
{ item: 'h', info: 'Info of h' },
{ item: 'i', info: 'Info of i' }
]
}, {
item: 'Item 4', submenus: [
{ item: 'j', info: 'Info of j' },
{ item: 'k', info: 'Info of k' },
{ item: 'l', info: 'Info of l' }
]
}];
Then in your HTML, we will loop over the menus using ngFor
<div *ngFor="let menu of menus; let i = index">
<!-- Menu -->
<div (click)="toggleMenu(i)" class="text-white cursor-pointer text-center">
<div class="py-4 bg-blue-600 hover:bg-blue-400">
{{menu.item}}
</div>
<div class="container" *ngIf="showSubmenu[i]">
<!-- Submenus -->
<ng-container *ngFor="let submenu of menu.submenus; let j = index">
<div (click)="toggleSubmenu($event, submenu.item)" class="py-3 w-1/3 inline-block"
[ngClass]="{'bg-blue-200': j === 0, 'bg-blue-300': j === 1, 'bg-blue-400': j === 2}">
{{submenu.item}}
</div>
</ng-container>
<!-- Information -->
<div *ngFor="let submenu of menu.submenus; let j = index">
<div *ngIf="showInfo[submenu.item]" (click)="$event.stopPropagation()" class="py-3 bg-green-400">
{{submenu.info}}
</div>
</div>
</div>
</div>
</div>
In your component, we shall define the flags and the toggle functions. I have used an array for flags. We will dynamically insert the toggle flag into this array based on the index. $event.stopPropagation is used to prevent the click event from bubbling up into the parent element's click event. Here's how the component will look
showSubmenu: any[] = [];
showInfo: any[] = [];
toggleMenu(index: number) {
this.showSubmenu[index] = !this.showSubmenu[index];
}
toggleSubmenu(event: MouseEvent, item: string) {
event.stopPropagation();
this.showInfo[item] = !this.showInfo[item];
}
Note: The item passed to thetoggleSubmenu should be a unique value. If you have an id, it would be preferred to use that here instead of item.
Here is a working StackBlitz of the same.