Angular 5中json对象的动态嵌套材质菜单
Posted
技术标签:
【中文标题】Angular 5中json对象的动态嵌套材质菜单【英文标题】:Dynamic nested Material menu from json object in Angular 5 【发布时间】:2018-06-17 04:31:20 【问题描述】:如何从 json 对象创建动态嵌套菜单?
我今天第一次开始使用 Angular Material Design,我正在尝试使用 Material Design 创建嵌套菜单。 documentation 非常直接用于静态内容。
但是我需要从 json 对象创建动态嵌套菜单,我无法在任何地方找到一个简单的解决方案。它只需要一层深。
json 对象(不是一成不变的):
my_menu =
'main1': ['sub1', 'sub2'],
'main2': ['sub1', 'sub2'],
会动态生成类似这样的内容:expected result example at 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>
我知道这是错误的,但这就是我对 angular 的理解结束的地方。
objectKeys 只是使用从 ts 文件加载的 Object.keys
返回对象的所有键。
objectKeys = Object.keys;
PS。我对 Angular 也很陌生
【问题讨论】:
【参考方案1】:以下结构应该适合您:
<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>
由于我在嵌入模板 (*ngFor
) 中放置了 sub_menu
,因此我们可以为模板引用变量 (#sub_menu
) 使用相同的名称。
Stackblitz Example
【讨论】:
非常感谢您的回答。我将扩展问题,为此,我将与您的名字保持一致。如果我有一个带有 subItem 数组的 mainItem 和一个没有 subItems 的 mainItem 如何以动态方式从没有任何子项的 mainItem 中消失箭头? @yurzui 忽略代码风格,我不得不承认这个解决方案背后的想法很漂亮。为了在顶部使用不同的菜单项类型实现类似的效果,我使用了 TemplateOutlets 和 ngContainers 的组合来结束它,但是这里的这个 sn-p 是重构我的代码的合理理由:) 谢谢! btw...objectKeys...既大胆又令人印象深刻,不错:)【参考方案2】:Here is a StackBlitz example 基于 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>
【讨论】:
我也在寻找在需要开发的 Angular 6/7 应用程序中构建动态菜单/选项卡。我对 Angular 有一些了解,并且有构建路线(预定义),但还没有使用过 Angular 材料。请告知我们是否需要 Angular 材料来完成这种功能,或者没有它也可以实现它?此外,我需要水平和垂直菜单/子菜单。 我写了一个库来处理菜单的动态渲染,你可以在这里找到它:github.com/klemenoslaj/ng-action-outlet 和演示:stackblitz.com/edit/ng-action-outlet-demo 注意:最好使用 Angular 提供的ng-container
元素,这样您就不会在菜单的同一个父级中拥有多个 <span>
元素。
这应该被标记为正确答案,你只是用这个实现救了我,我从来没想过在它自己内部调用一个组件。
为了让它在 Angular 10 中工作,我必须将 static: true
添加到 viewChild
以上是关于Angular 5中json对象的动态嵌套材质菜单的主要内容,如果未能解决你的问题,请参考以下文章
Angular 嵌套拖放 / CDK 材质 cdkDropListGroup cdkDropList nested
如何在 Angular 中为嵌套的 JSON 对象使用搜索过滤器?