web-dev-qa-db-ja.com

Angular 5のjsonオブジェクトからの動的なネストされたマテリアルメニュー

JSONオブジェクトから動的にネストされたメニューを作成する方法は?

今日初めてAngular Material Designを使用し始め、Material Designを使用してネストされたメニューを作成しようとしています。 documentation は静的なものについてはかなり単純です。

しかし、jsonオブジェクトから動的にネストされたメニューを作成する必要があり、これに対する簡単な解決策はどこにも見つかりません。深さは1レベルである必要があります。

jsonオブジェクト(石に設定されていない):

my_menu = {
    'main1': ['sub1', 'sub2'],
    'main2': ['sub1', 'sub2'],
}

これは動的に次のようなものを生成します: stackblitz での予期される結果の例

how it looks

メインメニューでこのように*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>

私はそれが間違っていることを知っていますが、それがangular。

objectKeysは、tsファイルからロードされたObject.keysを使用して、オブジェクトのすべてのキーを返すだけです。

objectKeys = Object.keys;

PS。 Angularも

18
rain01

次の構造が機能するはずです。

<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>

sub_menu埋め込みテンプレート内(*ngFor)テンプレート参照変数に同じ名前を使用できます(#sub_menu)。

Stackblitzの例

28
yurzui

ここにStackBlitzの例があります JSONに基づく任意の深さのネスト(@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() {
  }
}
<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>
6
Datum Geek