Angular:如何从数据库数据(Asp Net Core Web API数据)创建角度动态菜单

2024-04-25

我正在使用 Angular 11。我不知道如何在 Angular 中创建动态菜单。

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


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

1.-在互联网上寻找您喜欢的菜单/子菜单,例如我得到了我发现的第一个这个链接 http://www.falconmasters.com/tutoriales/como-hacer-un-menu-desplegable/(我发现第一个)。您可以寻找侧面导航菜单或您想要的类似内容。一般来说,它是这样的:

<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.-思考变量、数组和对象。并尝试使用变量重新创建

你看到菜单“item”有一个标签,和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路由器链接 https://angular.io/guide/router#defining-a-basic-route

<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 https://stackoverflow.com/questions/56376237/create-tree-view-with-horizontal-and-vertical-lines-showing-the-connectivity-usi/56381812#56381812

@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”中的两个表,并使用映射创建一个新对象,该对象是表“menu”加上一个附加属性“children”,其中包含 menuId==x.id 的子菜单

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

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

And use

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

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

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

Update好吧,获得“菜单”和“子菜单”表确实是一个“糟糕的设计”,

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

     })}
     )
  }

看到我们所有的角度应用程序都有效,唯一的就是更改“服务”

See a 堆栈闪电战 https://stackblitz.com/edit/angular-ivy-cjhjaw?file=src%2Fapp%2Fapp.component.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular:如何从数据库数据(Asp Net Core Web API数据)创建角度动态菜单 的相关文章

随机推荐