title: Dynamically nested angular material menu
body: <p>Please tell me how I can solve the following problem:
  I need to implement a dynamically created menu with different nesting levels depending on the data model object. At the moment, using recursion, we managed to create the menu as such, however, there is a problem of assigning the attribute [matMenuTriggerFor] for, directly, the submenu. The problem is that all subsequent submenus in fact refer to the very first, so when you hover over any of the submenus, it causes a "flip" to the original one (example on image: menu, which includes elements: Device, Extension, Queue, Queue member (with submenu elements)). Thus, for a fraction of seconds, I see the other submenu frame (example on image: submenu Grouped list), after which the very first becomes active. Of course, maybe I didn’t do everything right, so I’m turning here. Help me please. Thank you all.</p>
  
  <p><a href="https://i.stack.imgur.com/Xzoq1.png" rel="noreferrer"><img src="https://i.stack.imgur.com/Xzoq1.png" alt="Dynamically nested material menu"></a></p>
  
  <p><strong>imenu-item.ts</strong></p>
  
  <pre><code>export interface IMenuItem {
    name: string | string[];
    link: string;
    subItems: IMenuItem[];
  }
  </code></pre>
  
  <p><strong>dynamic-menu.service.ts</strong></p>
  
  <pre><code>import {Inject, Injectable} from '@angular/core';
  import {APP_CONFIG_ROUTES} from '../../../config/routes/app.config.routes';
  import {IAppConfigRoutes} from '../../../config/routes/iapp.config.routes';
  import {IMenuItem} from './imenu-item';
  import {_} from '@biesbjerg/ngx-translate-extract/dist/utils/utils';
  
  @Injectable({
    providedIn: 'root'
  })
  export class DynamicMenuService {
    private readonly appConfig: any;
  
    constructor(@Inject(APP_CONFIG_ROUTES) appConfig: IAppConfigRoutes) {
      this.appConfig = appConfig;
    }
  
    getMenuItems(): IMenuItem[] {
      return [
        {
          name: _('labels.device'),
          link: '/' + this.appConfig.routes.device,
          subItems: null
        },
        {
          name: _('labels.extension'),
          link: '/' + this.appConfig.routes.extension,
          subItems: null
        },
        {
          name: _('labels.queue'),
          link: '/' + this.appConfig.routes.queue,
          subItems: null
        },
        {
          name: _('labels.queueMember'),
          link: null,
          subItems: [{
            name: _('labels.fullList'),
            link: '/' + this.appConfig.routes.queueMember.all,
            subItems: null
          }, {
            name: _('labels.groupedList'),
            link: '/' + this.appConfig.routes.queueMember.grouped,
            subItems: [{
              name: 'subName',
              link: 'subLink',
              subItems: [{
                name: 'subSubName1',
                link: 'subSubLink1',
                subItems: null
              }, {
                name: 'subSubName2',
                link: 'subSubLink2',
                subItems: null
              }]
            }]
          }]
        }
      ];
    }
  }
  </code></pre>
  
  <p><strong>dynamic-menu.component.ts</strong></p>
  
  <pre><code>import {Component, Input, OnInit} from '@angular/core';
  import {IMenuItem} from './imenu-item';
  
  @Component({
    selector: 'app-dynamic-menu',
    templateUrl: './dynamic-menu.component.html',
    styleUrls: ['./dynamic-menu.component.scss']
  })
  export class DynamicMenuComponent implements OnInit {
    dynamicMenuItemsData: IMenuItem[];
  
    constructor(private dynamicMenuService: DynamicMenuService) {
    }
  
    ngOnInit() {
     this.dynamicMenuItemsData = this.dynamicMenuService.getMenuItems();
    }
  }
  </code></pre>
  
  <p><strong>dynamic-menu.component.html</strong></p>
  
  <pre><code>&lt;div&gt;
    &lt;ng-container [ngTemplateOutlet]="recursiveListMenuItems"
                  [ngTemplateOutletContext]="{$implicit: dynamicMenuItemsData}"&gt;
    &lt;/ng-container&gt;
  &lt;/div&gt;
  
  &lt;ng-template #recursiveListMenuItems let-listMenuItems&gt;
    &lt;div *ngFor="let menuItem of listMenuItems"&gt;
      &lt;ng-container [ngTemplateOutlet]="menuItem.subItems != null ? subMenuItem : simpleMenuItem"
                    [ngTemplateOutletContext]="{$implicit: menuItem}"&gt;
      &lt;/ng-container&gt;
    &lt;/div&gt;
  &lt;/ng-template&gt;
  
  &lt;ng-template #simpleMenuItem let-menuItemArg&gt;
    &lt;a class="mat-button"
       mat-menu-item
       routerLink="{{menuItemArg.link}}"&gt;
      &lt;span&gt;{{menuItemArg.name | translate}}&lt;/span&gt;
    &lt;/a&gt;
  &lt;/ng-template&gt;
  
  &lt;ng-template #subMenuItem let-menuItemArg&gt;
    &lt;a class="mat-button"
       mat-menu-item
       routerLink="{{menuItemArg.link}}"
       [matMenuTriggerFor]="subItemsMenu"&gt;
      &lt;span&gt;{{menuItemArg.name | translate}}&lt;/span&gt;
      &lt;mat-menu #subItemsMenu="matMenu"
                [overlapTrigger]="false"&gt;
        &lt;ng-container [ngTemplateOutlet]="recursiveListMenuItems"
                      [ngTemplateOutletContext]="{$implicit: menuItemArg.subItems}"&gt;
        &lt;/ng-container&gt;
      &lt;/mat-menu&gt;
    &lt;/a&gt;
  &lt;/ng-template&gt;
  </code></pre>