在 Angular 中使用 ngFor 循环时仅显示一次多个相同的值

Display multiple same values only once while others are looping using ngFor in Angular

我有以下来自服务器的示例数据集。

[
    {
        subMenuId: 1,
        submenu: 'Users',
        menu: 'Administration',
        url: '/pms/admin/usrs-dsh',
        icon: 'fas fa-cogs',
    },
    {
        subMenuId: 2,
        submenu: 'Roles',
        menu: 'Administration',
        url: '/pms/admin/roles-dsh',
        icon: 'fas fa-cogs',
    },
    {
        subMenuId: 3,
        submenu: 'Menu Items',
        menu: 'Administration',
        url: '/pms/admin/menus-dsh',
        icon: 'fas fa-cogs',
    },
    {
        subMenuId: 4,
        submenu: 'Banks',
        menu: 'Administration',
        url: '/pms/admin/banks-dsh',
        icon: 'fas fa-cogs',
    },
    {
        subMenuId: 5,
        submenu: 'Branches',
        menu: 'Administration',
        url: '/pms/admin/branches-dsh',
        icon: 'fas fa-cogs',
    },
    {
        subMenuId: 6,
        submenu: 'Dashboard',
        menu: 'PD3',
        url: '/pms/pd3/dsh',
        icon: 'fas fa-cogs',
    },

];

我想像这样显示这些数据。但目前在显示数据时,主级别值与每个子级别值重复。 预期输出

我的输出:

Html 文件:

 <tr *ngFor="let m of userPermissions;">
                        <td>
                            <label class="ml-3 form-check-label">{{m.menu}}</label>
                        </td>
                        <td>
                            <div>
                                <input (change)="changeSubMenus($event, m.menu,m.subMenuId)" type="checkbox" class="ml-0 form-check-input">
                                <label class="ml-3 form-check-label">{{m.submenu}}</label><br>
                            </div>
                        </td>
                    </tr>

TS 文件:

getMenus(){
  this.userPermissions = this.adminService.allMenus;
  
  this.userPermissions.forEach((val) =>{
     // console.log(val)
     // TODO: remove multiple main level values and display sub level values with one main level value
  })

}

有什么办法可以做到这一点。 谢谢

您需要修改数组中的对象才能达到您想要的要求。您可以像下面那样使用 reduce

你需要像下面这样的对象结构,让事情变得更简单

modifiedMenu = [{
  menu: < Main Menu 1 > ,
  subMenu: [ < submenu item > , < submenu item > , ...]
}, {
  menu: < Main Menu 2 > ,
  subMenu: [ < submenu item > , < submenu item > , ...]
}, ...]

所以,原来的是

userPermissions = this.menus.reduce((acc, ele) => {
  if (acc.length === 0) {
    acc.push(this.getModifiedMainMenu(ele));
    return acc;
  } else {
    const existedMenu = acc.find(m => m.menu === ele.menu);
    if (existedMenu) {
      existedMenu.subMenu.push(this.getSubMenu(ele));
      return acc;
    } else {
      acc.push(this.getModifiedMainMenu(ele));
      return acc;
    }
  }
}, []);

getModifiedMainMenu(obj) {
  return {
    menu: obj.menu,
    subMenu: [this.getSubMenu(obj)]
  };
}

getSubMenu(obj) {
  return {
    menu: obj.menu,
    subMenuId: obj.subMenuId,
    submenu: obj.submenu,
    url: obj.url,
    icon: obj.icon
  };
}

并且在模板文件中,现在您需要 2 ngFor 来循环主菜单项和相应的子菜单项,如下所示

<tr *ngFor="let m of userPermissions;">
  <td>
    <label class="ml-3 form-check-label">{{m.menu}}</label>
  </td>
  <td>
    <div *ngFor="let subMenu of m.subMenu">
      <input (change)="changeSubMenus($event, subMenu.menu, subMenu.subMenuId)" type="checkbox" class="ml-0 form-check-input">
      <label class="ml-3 form-check-label">{{subMenu.submenu}}</label>
    </div>
  </td>
</tr>

工作Stackblitz