Angular 基于另一个数组的嵌套数组过滤(导航菜单)

Angular nested array filtering based on another array (Navigation menu)

我有一个导航菜单+一个用户角色列表。它实际上是一个遗留应用程序,这就是为什么我有这么多用户角色。

基本上,我想根据用户的角色显示导航菜单。

下面给出了用户角色数组和导航项数组。

基本上,我想通过将其与用户角色进行比较来减少导航项数组。

用户角色数组:

["ABS","ADM","AUTH","BAGGED","BLQ3E","MUMA12","MUMA13","MUMA14","MUMP12","MUMP13","MUMP14","MUMADM","MANAGER","SAF_ADM","XXXDDD","CRYPTRESP","SCHEDULEADM","INTERNALUSER","INTERNALMANAGER","GROUPHEAD","USER"]

导航项数组

export interface NavItem {
  displayName: string;
  disabled?: boolean;
  iconName: string;
  route?: string;
  children?: Array<NavItem>;
  role: string[];
}


navItems: Array<NavItem> = [
    {
      displayName: 'Accounts',
      iconName: 'account_circle',
      route: 'dummyroute',
      role: ['USER'],
      children: [
        {
          displayName: 'My Account',
          iconName: 'group',
          route: 'devfestfl/speakers',
          role: ['USER'],
        },
        {
          displayName: 'Change My Password',
          iconName: 'password',
          route: 'devfestfl/sessions',
          role: ['USER'],
        },
        {
          displayName: 'Manage Other Accounts',
          iconName: 'manage_accounts',
          route: 'devfestfl/feedback',
          role: ['ADM'],
        },
        {
          displayName: 'XXXX Accounts',
          iconName: 'account_tree',
          route: 'devfestfl/feedback',
          role: ['ADM'],
        },
        {
          displayName: 'XXXX',
          iconName: 'account_tree',
          route: 'dummyroute',
          role: ['ADM', 'SAF_ADM']
        }
      ]
    },
    {
      displayName: 'First Menu Item',
      iconName: 'dock',
      route: 'dummyroute',
      role: ['CRYPTRESP', 'SCHEDULEADM', 'BLSTAFF', 'ADM', 'CRG_USER', 'USER'],
      children: [
        {
          displayName: 'XX Menu Item',
          iconName: '',
          route: 'dummy',
          role: ['USER'],
        },
        {
          displayName: 'YY Menu Item',
          iconName: '',
          route: 'dummy',
          role: ['ADM'],
        },
        {
          displayName: 'ZZ Menu Item',
          iconName: '',
          route: 'dummy',
          role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM'],
        }
        {
          displayName: 'PP Management',
          iconName: '',
          route: 'dummy',
          role: ['ADM', 'BAGGED'],
          children: [
            {
              displayName: 'PP Datasets',
              iconName: '',
              route: 'dummy',
              role: ['ADM'],
            },
            {
              displayName: 'PP Groups',
              iconName: '',
              route: 'dummy',
              role: ['BAGGED'],
            }
          ]
        },
        {
          displayName: 'Beamline Schedule',
          iconName: '',
          route: 'beamlineschedule',
          role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM', 'BLSTAFF', 'INTERNALMANAGER'],
          children: [
            {
              displayName: 'Manage Schedule',
              iconName: '',
              route: 'manageschedule',
              role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM', 'BLSTAFF', 'INTERNALMANAGER'],
            },
            {
              displayName: 'Show Finalized Runs',
              iconName: '',
              route: 'showfinalizedruns',
              role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM'],
            },
            {
              displayName: 'Scheduling Bulk Import',
              iconName: '',
              route: 'schedulingbulkimport',
              role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM'],
            },
            {
              displayName: 'Beamline Accounts',
              iconName: '',
              route: 'beamlineaccounts',
              role: ['ADM', 'ABS', 'BLQ3E'],
            }
          ]
        },
        {
          displayName: 'Machine Operation Schedule',
          iconName: '',
          route: 'machineoperationschedule',
          role: ['ADM'],
        },
        {
          displayName: 'End of Shift Forms',
          iconName: '',
          route: 'feedbackforms',
          role: ['ADM'],
        },
        {
          displayName: 'External Funded Proposals',
          iconName: '',
          route: 'externalfundedproposals',
          role: ['ADM'],
          children: [
            {
              displayName: 'Submitted Reports',
              iconName: '',
              route: 'submittedreports',
              role: ['ADM'],
            },
            {
              displayName: 'Pending Reports',
              iconName: '',
              route: 'pendingreports',
              role: ['ADM'],
            },
            {
              displayName: 'iNEXT-Discovery Proposals',
              iconName: '',
              route: 'inextdproposals',
              role: ['ADM'],
            }
          ]
        }
      ],
    },
    {
      displayName: 'Safety',
      iconName: 'health_and_safety',
      route: 'dummy',
      role: ['ADM', 'USER'],
      children: [
        {
          displayName: 'Safety child menu',
          iconName: '',
          route: 'dummy',
          role: ['ADM', 'USER'],
          children: [
            {
              displayName: 'safety grandchild',
              iconName: '',
              route: 'dummy',
              role: ['ADM', 'USER'],
            },
            {
              displayName: 'grandchild2',
              iconName: '',
              route: 'dummy',
              role: ['ADM', 'USER'],
            }
          ]
        },
        {
          displayName: 'safety second child menu',
          iconName: '',
          route: 'dummy',
          role: ['ADM'],
        }
      ]
    },
  ];

到目前为止我尝试过的都失败了。我最接近的是如下。我很确定我做错了什么,因为它根本不起作用。

for (var navitem of this.navItems) {
  for (var userrole of this.userRolesArray) {
    if (navitem.role.some(item => item.includes(userrole))) {
      if (!this.newNavItemsArray.includes(navitem)) {
        for (var navchild of navitem.children) {
          if (navchild.role.some(item => item.includes(userrole))) {
            this.newNavItemsArray.push({ navitem, children: [navchild] })
          }
        }
      }
    }
  }
}

请帮忙:)

我采用了一种不同的方法,使用 reduce 和一些 some 方法。我假设如果目标角色不在主导航中,它应该跳过 children。这将一组角色作为参数并过滤导航以适应

const getNavForRole = (roles) => {
  return navItems.reduce((b, a) => {
    if (!a.role.some(r => roles.includes(r))) return b;
    a.children = a.children.filter(f => f.role.some(r => roles.includes(r)))
    return [...b, a]
  }, [])
}

let navItems = [{
    displayName: 'Accounts',
    iconName: 'account_circle',
    route: 'dummyroute',
    role: ['USER'],
    children: [{
        displayName: 'My Account',
        iconName: 'group',
        route: 'devfestfl/speakers',
        role: ['USER'],
      },
      {
        displayName: 'Change My Password',
        iconName: 'password',
        route: 'devfestfl/sessions',
        role: ['USER'],
      },
      {
        displayName: 'Manage Other Accounts',
        iconName: 'manage_accounts',
        route: 'devfestfl/feedback',
        role: ['ADM'],
      },
      {
        displayName: 'XXXX Accounts',
        iconName: 'account_tree',
        route: 'devfestfl/feedback',
        role: ['ADM'],
      },
      {
        displayName: 'XXXX',
        iconName: 'account_tree',
        route: 'dummyroute',
        role: ['ADM', 'SAF_ADM']
      }
    ]
  },
  {
    displayName: 'First Menu Item',
    iconName: 'dock',
    route: 'dummyroute',
    role: ['CRYPTRESP', 'SCHEDULEADM', 'BLSTAFF', 'ADM', 'CRG_USER', 'USER'],
    children: [{
        displayName: 'XX Menu Item',
        iconName: '',
        route: 'dummy',
        role: ['USER'],
      },
      {
        displayName: 'YY Menu Item',
        iconName: '',
        route: 'dummy',
        role: ['ADM'],
      },
      {
        displayName: 'ZZ Menu Item',
        iconName: '',
        route: 'dummy',
        role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM'],
      }, {
        displayName: 'PP Management',
        iconName: '',
        route: 'dummy',
        role: ['ADM', 'BAGGED'],
        children: [{
            displayName: 'PP Datasets',
            iconName: '',
            route: 'dummy',
            role: ['ADM'],
          },
          {
            displayName: 'PP Groups',
            iconName: '',
            route: 'dummy',
            role: ['BAGGED'],
          }
        ]
      },
      {
        displayName: 'Beamline Schedule',
        iconName: '',
        route: 'beamlineschedule',
        role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM', 'BLSTAFF', 'INTERNALMANAGER'],
        children: [{
            displayName: 'Manage Schedule',
            iconName: '',
            route: 'manageschedule',
            role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM', 'BLSTAFF', 'INTERNALMANAGER'],
          },
          {
            displayName: 'Show Finalized Runs',
            iconName: '',
            route: 'showfinalizedruns',
            role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM'],
          },
          {
            displayName: 'Scheduling Bulk Import',
            iconName: '',
            route: 'schedulingbulkimport',
            role: ['ADM', 'CRYPTRESP', 'SCHEDULEADM'],
          },
          {
            displayName: 'Beamline Accounts',
            iconName: '',
            route: 'beamlineaccounts',
            role: ['ADM', 'ABS', 'BLQ3E'],
          }
        ]
      },
      {
        displayName: 'Machine Operation Schedule',
        iconName: '',
        route: 'machineoperationschedule',
        role: ['ADM'],
      },
      {
        displayName: 'End of Shift Forms',
        iconName: '',
        route: 'feedbackforms',
        role: ['ADM'],
      },
      {
        displayName: 'External Funded Proposals',
        iconName: '',
        route: 'externalfundedproposals',
        role: ['ADM'],
        children: [{
            displayName: 'Submitted Reports',
            iconName: '',
            route: 'submittedreports',
            role: ['ADM'],
          },
          {
            displayName: 'Pending Reports',
            iconName: '',
            route: 'pendingreports',
            role: ['ADM'],
          },
          {
            displayName: 'iNEXT-Discovery Proposals',
            iconName: '',
            route: 'inextdproposals',
            role: ['ADM'],
          }
        ]
      }
    ],
  },
  {
    displayName: 'Safety',
    iconName: 'health_and_safety',
    route: 'dummy',
    role: ['ADM', 'USER'],
    children: [{
        displayName: 'Safety child menu',
        iconName: '',
        route: 'dummy',
        role: ['ADM', 'USER'],
        children: [{
            displayName: 'safety grandchild',
            iconName: '',
            route: 'dummy',
            role: ['ADM', 'USER'],
          },
          {
            displayName: 'grandchild2',
            iconName: '',
            route: 'dummy',
            role: ['ADM', 'USER'],
          }
        ]
      },
      {
        displayName: 'safety second child menu',
        iconName: '',
        route: 'dummy',
        role: ['ADM'],
      }
    ]
  },
];


const getNavForRole = (roles) => {
  return navItems.reduce((b, a) => {
    if (!a.role.some(r => roles.includes(r))) return b;
    a.children = a.children.filter(f => f.role.some(r => roles.includes(r)))
    return [...b, a]
  }, [])
}

console.log(getNavForRole(['CRYPTRESP','USER']))