使用JSON创建动态多级菜单

3

问题

我正在尝试在Angular中使用JSON创建动态的多级主导航(菜单)。

在AngularJS中,我会定义一个模板并递归使用它来动态创建额外的菜单级别。

然而,在Angular中,我无法找到一种方法来动态创建这些级别的菜单。

目前,我已将其硬编码以允许两个级别,但如果未来需要添加更多级别,则每个级别都必须硬编码才能正常工作。

我正在寻找一种基于返回的菜单JSON动态执行此操作的方法。

JSON

menu = [
  {
    title: "Menu Item 1",
        url: "/",
        target: "_blank"
    },
    {
    title: "Menu Item 2",
        active: true,
        navigationItems: [
            {
              title: "Sub-Menu Item 1",
              url: "/"
            },
            {
              title: "Sub-Menu Item 2",
              url: "/",
              navigationItems: [
                  {
                      title: "This Level Not Supported Without Hard-Coding"
                  }
              ]
            }
        ]
    }
]

标记语言

<div>
    <ul role="menubar">
        <li *ngFor="let link of menu; let i = index;">

            <a 
              [attr.href]="link.href ? link.href : null"
              [attr.target]="link.target ? link.target : null"
              aria-role="menuitem"
              [attr.ariaExpanded]="link.navigationItems && openElements[i] ? true : null"
              [attr.ariaHasPopup]="link.navigationItems ? true : null"
              (click)="link.navigationItems ? openElements[i] = !openElements[i] : null"
              [class]="openElements[i] ? 'open' : null"
            >
              {{link.title}}
            </a>

            <ul *ngIf="link.navigationItems" role="menu">
                <li *ngFor="let link of link.navigationItems">
                    <a [attr.href]="link.url"
                        [innerHTML]="link.title"
                        [attr.target]="link.target ? link.target : null"
                        role="menuitem"
                    >
                    </a>
                </li>
            </ul>

        </li>
    </ul>
</div>

一个工作示例

https://plnkr.co/edit/lpLxHlKtwCJUukoruxq2?p=preview

解决方案

我需要一种方法来确保根据附加到组件的数据服务返回的JSON的结构,可以添加任意数量的级别到此菜单中,而无需在标记中为每个级别硬编码级别。


我相当长时间以前就发布了这个问题的答案。您也可以在https://stackoverflow.com/a/61746097/9590251上查看它。 - Timothy
1个回答

10

设置自定义递归组件

NavItem.d.ts

export interface NavItem {
  title: string;
  active: boolean;
  target: string;
  url: string;
  navigationItems: NavItem[];
}

NavItem.component.ts

import { Component, Input } from '@angular/core';
import { NavItem } from 'NavItem.d.ts';

@Component({
  selector: 'nav-item',
  template: 'NavItem.component.html'
})
export class NavItemComponent {

    @Input() private navItems: NavItem[];

    constructor() {
    }
}

NavItem.component.html

<ul role="menubar">
  <li *ngFor="let item of navItems">
    <a ...>{{ item.title }}</a>
    <nav-item *ngIf="item.navigationItems" [navItems]="item.navigationItems"></nav-item>
  </li>
</ul>

用法:在已经可以访问navItems的现有模板内部

<nav-item [navItems]="navItems"></nav-item>

1
请问您能否展示一个动态创建多个层级的实现方式? - StephenRios
@StephenRios,我不太确定你在问什么。您可以像使用其他自定义组件一样使用它。假设您已经加载了所有的NavItems,在现有模板中,您将有一个<nav-item navItems="navItems"></nav-item>。嵌套组件将自动生成。上面唯一遗漏的是在模块中注册。 - ChrisG
那个实现正是我在寻找的,这样答案就会完整。如果你将它添加到你的答案中,我会很乐意接受它。 - StephenRios
3
好的,以下是您需要翻译的内容:https://stackblitz.com/edit/dynamic-material-menu-angular-8?file=src%2Fapp%2Fmenu-overview-example.ts这是一个Angular 8项目示例,它演示了如何使用Angular Material创建动态菜单。该示例使用MatMenu和MatMenuItem组件,并展示了如何在组件之间共享数据以及如何响应菜单项的点击事件。若要查看示例,请点击链接并打开menu-overview-example.ts文件。 - sheucm
@sheucm 谢谢伙计,正是我想要的。 - Peter Maher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接