Home > Back-end >  Angular nested array filtering based on another array (Navigation menu)
Angular nested array filtering based on another array (Navigation menu)

Time:01-09

I have a navigation menu a list of user roles. It's actually a legacy application and that's why I have so many user roles.

Basically, I want to show the navigation menu based on the roles the user has.

  • A user can have multiple roles.
  • A menu item can be accessed by multiple roles.
  • Compare the role mentioned in the menu item and child menu item with the user role array.

Both User role array and Navigation Item array are given below.

Basically, I want to reduce the navigation item array by comparing it to the user role.

User Role Array:

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

Nav Item array

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'],
        }
      ]
    },
  ];

What I've tried until now has failed. The closest I've come is as below. I'm pretty sure I'm doing something wrong because it just doesn't work.

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] })
          }
        }
      }
    }
  }
}

Please help :)

CodePudding user response:

I took a different approach using reduce and a couple some methods. I assumed that if the target role was not in the main nav, it should skip the children. This takes an array of roles as the argument and filters down the navigation to accomodate

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']))

  •  Tags:  
  • Related