【问题标题】:Angular : How to create a dynamic menu in angular from database data (Asp net core Web API data)Angular:如何从数据库数据(Asp net core Web API 数据)中以角度创建动态菜单
【发布时间】:2021-09-14 22:07:17
【问题描述】:

我正在使用 angular 11。我不知道用 angular 创建动态菜单。

实际上我在数据库中创建了两个表(即 MainMenu 和 subMenu)。为此,我必须在 .net Core 中创建一个 aspnet core web api,并希望将 aspnet core web api 数据绑定到 angular [意味着要从 aspnet core web api 数据创建一个动态菜单 angular]。

【问题讨论】:

    标签: angular


    【解决方案1】:

    这是一个宽泛的问题,你给我们的线索很少。所以我简单地指出一个“通用方法”。

    1.-在互联网上寻找您喜欢的菜单/子菜单,例如我得到了我在this link 中找到的第一个(我找到的第一个)。你可以寻找一个侧面导航菜单或你想要的那样。一般来说,它是在路上:

    <div id="header">
      <ul class="nav">
        <li><a href="">Home</a></li>
        <li><a href="">Services</a>
          <ul>
            <li><a href="">Submenu1</a></li>
            <li><a href="">Submenu2</a></li>
            <li><a href="">Submenu3</a></li>
            <li><a href="">Submenu4</a>
              <ul>
                <li><a href="">Submenu1</a></li>
                <li><a href="">Submenu2</a></li>
                <li><a href="">Submenu3</a></li>
                <li><a href="">Submenu4</a></li>
              </ul>
            </li>
          </ul>
        </li>
        <li><a href="">About</a>
          <ul>
            <li><a href="">Submenu1</a></li>
            <li><a href="">Submenu2</a></li>
            <li><a href="">Submenu3</a></li>
            <li><a href="">Submenu4</a></li>
          </ul>
        </li>
        <li><a href="">Contact</a></li>
      </ul>
    </div>
    

    2.-考虑变量、数组和对象。并尝试使用变量重新创建

    您会看到菜单“项目”具有标签和href,因此或多或少是{label:"...",href:"..",children:[...]},是的,子项是该对象的简单数组。想象一些像

      menu=[
        {href:"",label:"Home"},
        {href:"",label:"Servicios",children:[
            {href:"",label:"Submenu1"},
            {href:"",label:"Submenu2"},
            {href:"",label:"Submenu3"},
            {href:"",label:"Submenu4",children:[
                {href:"",label:"Submenu1"},
                {href:"",label:"Submenu2"},
                {href:"",label:"Submenu3"},
                {href:"",label:"Submenu4"}
            ]},
        ]},
        {href:"",label:"About",children:[
            {href:"",label:"Submenu1"},
            {href:"",label:"Submenu2"},
            {href:"",label:"Submenu3"},
            {href:"",label:"Submenu4"}
            ]},
        {href:"",label:"Contact"}                                       
        ]
    

    我们可以想象这样显示这个对象使用*ngFor 和*ngIf。在 Angular 中,我们不使用 href else routerLink

    <div id="header">
      <ul class="nav">
        <li *ngFor="let item of menu">
          <a [routerLink]="item.href">{{item.label}}</a>
          <ul *ngIf="item.children">
            <li *ngFor="let submenu of item.children">
              <a [routerLink]="submenu.href">{{submenu.label}}</a>
              <ul *ngIf="submenu.children">
                <li *ngFor="let submenu2 of submenu.children">
                  <a [routerLink]="submenu2.href">{{submenu2.label}}</a>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </div>
    

    我们可以考虑做一个“递归”组件或符合这个“三个层次”。做一个递归组件不难,可以看this SO

    @Component({
      selector: '[recursive]',
      template: `
      <li *ngFor="let item of children">
        <a [routerLink]="item.href">{{item.label}}</a>
        <ul recursive *ngIf="item.children" 
            [children]="item.children" 
            [parent]="self" 
            [level]="level!=undefined?level+1:0">
        </ul>
    </li>
      `,
    })
    export class MenuItemComponent  {
      @Input() level: number;
      @Input() label: string;
      @Input() children: any[];
      @Input() parent: any;
    
      self=this;
    }
    

    和我们的 .html 一样

    <div id="header">
       <ul class="nav" recursive [children]="menu"></ul>
    </div>
    

    3.-创建对象。我们已准备好显示菜单,现在是时候使用表格创建对象“菜单”了

    与往常一样,我们有一项服务可以获取表格菜单和表格子菜单

    /*Imagine return an array like
     [{id:1,label:...,href:...},
      {id:2,label:...,href:...}..]
    */
    getMenu()
    {
       return this.http.get("myApi/menu");
    }
    
    /*Imagine return an array like
     [{id:1,label:...,href:...,menuId:1},
      {id:2,label:...,href:...,menuId:1}..]
    */
    getSubMenu()
    {
       return this.http.get("myApi/submenu");
    }
    

    所以我们可以创建一个新函数来获取这两个表并返回我们的对象“菜单”

      getObjectMenu() {
        return forkJoin([this.getMenu(), this.getSubMenu()]).pipe(
          map(([menu, submenu]: [any[], any[]]) => {
            return menu.map((x: any) => ({
              ...x,
              children: submenu.filter(s => s.menuId == x.id)
            }));
          })
        );
      }
    

    看到 forkJoin 基于 observable 数组创建了一个 observable。我们在“menu,submenu”中获取两个表,并使用 map 创建一个新对象,即表“menu”加上一个附加属性“children”,其中包含 menuId==x.id 的子菜单

    4.-在 Angular 应用程序中使用我们的服务。好了,现在,我们可以在 ngOnInit 中订阅服务并为变量赋值

    constructor(private menuService:MenuService){}
    ngOnInit()
    {
      this.menuService.getObjectMenu().subscribe(res=>{
        this.menuData=res
      })
    }
    

    并使用

    <div id="header">
       <ul class="nav" recursive [children]="menuData"></ul>
    </div>
    

    或者,当我们的 service.getObjectMenu() 返回一个 observable 时,我们可以使用管道异步

    <div id="header">
      <ul class="nav">
        <!--see that use menuService.getObjectMenu()|async-->
        <li *ngFor="let item of menuService.getObjectMenu()|async">
          <a [routerLink]="item.href">{{item.label}}</a>
          <ul *ngIf="item.children">
          ...
      </ul>
    </div>
    

    //或使用递归

    <div id="header">
       <ul class="nav" recursive [children]="menuService.getObjectMenu()|async">
       </ul>
    </div>
    

    更新好吧,获取“菜单”和“子菜单”表确实是“糟糕的设计”,

    5.-一般你只会得到一个唯一的表格每个元素的方式{ id: .., href:.., label: .., menuId: .. }

    如果 menuId=0 是菜单,否则是子菜单。所以我们可以想象一个函数

    getAllMenu()()
    {
       return this.http.get("myApi/menu");
    }
    

    如何创建我们的对象“menuObject”。作为递归,你需要记住你应该有一个被称为自身的函数。嗯,e可以有一个功能

      getObjectMenu() {
        return this.getAllMenu().pipe(
          map((menu: any[]) =>
            menu.filter(x=>!x.menuId).map(x => ({
              ...x, 
              children: this.getChildren(menu,x.id) //<--here call to function
            }))
          )
        );
      }
    
      getChildren(menu:any[],id:number){
         return menu.filter(x=>x.menuId==id).map((x:any)=>{
           return ({
           ...x,
           children:this.getChildren(menu,x.id) //<--see the function is called to itself
    
         })}
         )
      }
    

    看到我们所有的 Angular 应用程序都能正常工作,唯一的就是改变“服务”

    查看stackblitz

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 2012-10-31
      相关资源
      最近更新 更多