Angular 5中json对象的动态嵌套材质菜单

rai*_*n01 22 nested menu dynamic angular-material angular

如何从json对象创建动态嵌套菜单?

我今天第一次开始使用Angular Material Design,我正在尝试使用材质设计创建嵌套菜单.对于静态内容,文档非常简单.

但我需要从json对象创建动态嵌套菜单,我无法在任何地方找到一个简单的解决方案.它只需要一层深.

json对象(不是一成不变的):

my_menu = {
    'main1': ['sub1', 'sub2'],
    'main2': ['sub1', 'sub2'],
}
Run Code Online (Sandbox Code Playgroud)

这将生成类似这样但动态的:在stackblitz的预期结果示例

看起来如何

我尝试*ngFor在主菜单上运行这样的运行,然后在每个子菜单上分开,但它以错误结束.

<button mat-button [matMenuTriggerFor]="main_menu">My menu</button>

<mat-menu #main_menu="matMenu">
  <button *ngFor="let main_item of objectKeys(my_menu)" mat-menu-item [matMenuTriggerFor]="main_item">{{ main_item }}</button>
  <button mat-menu-item [matMenuTriggerFor]="main2">main2</button>
</mat-menu>

<mat-menu *ngFor="let sub_menu of objectKeys(my_menu)" #sub_menu="matMenu">
  <button *ngFor="let sub_name of sub_menu" mat-menu-item>{{ sub_name }}</button>
</mat-menu>
Run Code Online (Sandbox Code Playgroud)

我知道这是错的,但那是我对棱角的理解结束了.

objectKeys只返回Object.keys从ts文件加载的对象的所有键.

objectKeys = Object.keys;
Run Code Online (Sandbox Code Playgroud)

PS.我也是Angular的新手

yur*_*zui 33

以下结构应该适合您:

<button mat-button [matMenuTriggerFor]="main_menu">My menu</button>

<mat-menu #main_menu="matMenu">
  <ng-container *ngFor="let mainItem of objectKeys(my_menu)">
    <button mat-menu-item [matMenuTriggerFor]="sub_menu">{{ mainItem }}</button>
    <mat-menu #sub_menu="matMenu">
       <button *ngFor="let subItem of my_menu[mainItem]" mat-menu-item>{{ subItem }}</button>
    </mat-menu>
  </ng-container>
</mat-menu>
Run Code Online (Sandbox Code Playgroud)

由于我放置sub_menu在嵌入式模板(*ngFor)中,我们可以使用相同的名称作为模板引用变量(#sub_menu).

Stackblitz示例


Dat*_*eek 10

这是一个基于JSON的任意深度嵌套的StackBlitz示例(由@Splaktar编写)

任意嵌套的关键是自引用menu-item.component

import {Component, Input, OnInit, ViewChild} from '@angular/core';
import {Router} from '@angular/router';
import {NavItem} from '../nav-item';

@Component({
  selector: 'app-menu-item',
  templateUrl: './menu-item.component.html',
  styleUrls: ['./menu-item.component.scss']
})
export class MenuItemComponent implements OnInit {
  @Input() items: NavItem[];
  @ViewChild('childMenu') public childMenu;

  constructor(public router: Router) {
  }

  ngOnInit() {
  }
}
Run Code Online (Sandbox Code Playgroud)
<mat-menu #childMenu="matMenu" [overlapTrigger]="false">
  <span *ngFor="let child of items">
    <!-- Handle branch node menu items -->
    <span *ngIf="child.children && child.children.length > 0">
      <button mat-menu-item color="primary" [matMenuTriggerFor]="menu.childMenu">
        <mat-icon>{{child.iconName}}</mat-icon>
        <span>{{child.displayName}}</span>
      </button>
      <app-menu-item #menu [items]="child.children"></app-menu-item>
    </span>
    <!-- Handle leaf node menu items -->
    <span *ngIf="!child.children || child.children.length === 0">
      <button mat-menu-item [routerLink]="child.route">
        <mat-icon>{{child.iconName}}</mat-icon>
        <span>{{child.displayName}}</span>
      </button>
    </span>
  </span>
</mat-menu>
Run Code Online (Sandbox Code Playgroud)

  • 注意:最好使用Angular提供的ng-container元素,这样在菜单的同一父级中就不会有多个`&lt;span&gt;`元素。 (2认同)
  • 为了让它在 Angle 10 下工作,我必须将 `static: true` 添加到 `viewChild` 中 (2认同)