动态嵌套的角度材质菜单

tit*_*che 6 javascript typescript angular angular-material-6

Please tell me how I can solve the following problem:\nI 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\xe2\x80\x99t do everything right, so I\xe2\x80\x99m turning here. Help me please. Thank you all.

\n\n

动态嵌套材质菜单

\n\n

imenu-item.ts

\n\n
export interface IMenuItem {\n  name: string | string[];\n  link: string;\n  subItems: IMenuItem[];\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

dynamic-menu.service.ts

\n\n
import {Inject, Injectable} from \'@angular/core\';\nimport {APP_CONFIG_ROUTES} from \'../../../config/routes/app.config.routes\';\nimport {IAppConfigRoutes} from \'../../../config/routes/iapp.config.routes\';\nimport {IMenuItem} from \'./imenu-item\';\nimport {_} from \'@biesbjerg/ngx-translate-extract/dist/utils/utils\';\n\n@Injectable({\n  providedIn: \'root\'\n})\nexport class DynamicMenuService {\n  private readonly appConfig: any;\n\n  constructor(@Inject(APP_CONFIG_ROUTES) appConfig: IAppConfigRoutes) {\n    this.appConfig = appConfig;\n  }\n\n  getMenuItems(): IMenuItem[] {\n    return [\n      {\n        name: _(\'labels.device\'),\n        link: \'/\' + this.appConfig.routes.device,\n        subItems: null\n      },\n      {\n        name: _(\'labels.extension\'),\n        link: \'/\' + this.appConfig.routes.extension,\n        subItems: null\n      },\n      {\n        name: _(\'labels.queue\'),\n        link: \'/\' + this.appConfig.routes.queue,\n        subItems: null\n      },\n      {\n        name: _(\'labels.queueMember\'),\n        link: null,\n        subItems: [{\n          name: _(\'labels.fullList\'),\n          link: \'/\' + this.appConfig.routes.queueMember.all,\n          subItems: null\n        }, {\n          name: _(\'labels.groupedList\'),\n          link: \'/\' + this.appConfig.routes.queueMember.grouped,\n          subItems: [{\n            name: \'subName\',\n            link: \'subLink\',\n            subItems: [{\n              name: \'subSubName1\',\n              link: \'subSubLink1\',\n              subItems: null\n            }, {\n              name: \'subSubName2\',\n              link: \'subSubLink2\',\n              subItems: null\n            }]\n          }]\n        }]\n      }\n    ];\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

dynamic-menu.component.ts

\n\n
import {Component, Input, OnInit} from \'@angular/core\';\nimport {IMenuItem} from \'./imenu-item\';\n\n@Component({\n  selector: \'app-dynamic-menu\',\n  templateUrl: \'./dynamic-menu.component.html\',\n  styleUrls: [\'./dynamic-menu.component.scss\']\n})\nexport class DynamicMenuComponent implements OnInit {\n  dynamicMenuItemsData: IMenuItem[];\n\n  constructor(private dynamicMenuService: DynamicMenuService) {\n  }\n\n  ngOnInit() {\n   this.dynamicMenuItemsData = this.dynamicMenuService.getMenuItems();\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

dynamic-menu.component.html

\n\n
<div>\n  <ng-container [ngTemplateOutlet]="recursiveListMenuItems"\n                [ngTemplateOutletContext]="{$implicit: dynamicMenuItemsData}">\n  </ng-container>\n</div>\n\n<ng-template #recursiveListMenuItems let-listMenuItems>\n  <div *ngFor="let menuItem of listMenuItems">\n    <ng-container [ngTemplateOutlet]="menuItem.subItems != null ? subMenuItem : simpleMenuItem"\n                  [ngTemplateOutletContext]="{$implicit: menuItem}">\n    </ng-container>\n  </div>\n</ng-template>\n\n<ng-template #simpleMenuItem let-menuItemArg>\n  <a class="mat-button"\n     mat-menu-item\n     routerLink="{{menuItemArg.link}}">\n    <span>{{menuItemArg.name | translate}}</span>\n  </a>\n</ng-template>\n\n<ng-template #subMenuItem let-menuItemArg>\n  <a class="mat-button"\n     mat-menu-item\n     routerLink="{{menuItemArg.link}}"\n     [matMenuTriggerFor]="subItemsMenu">\n    <span>{{menuItemArg.name | translate}}</span>\n    <mat-menu #subItemsMenu="matMenu"\n              [overlapTrigger]="false">\n      <ng-container [ngTemplateOutlet]="recursiveListMenuItems"\n                    [ngTemplateOutletContext]="{$implicit: menuItemArg.subItems}">\n      </ng-container>\n    </mat-menu>\n  </a>\n</ng-template>\n
Run Code Online (Sandbox Code Playgroud)\n

tit*_*che 6

结果,事实证明,依赖于其他人的几个类似问题。来自HERE(动态嵌套菜单示例)和来自HERE(mat-menu 的问题在打开时立即隐藏)的示例有助于解决这个问题(在最后一个示例中,只需通过 更新就足够zone.jsnpm