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']))
我有一个导航菜单+一个用户角色列表。它实际上是一个遗留应用程序,这就是为什么我有这么多用户角色。
基本上,我想根据用户的角色显示导航菜单。
- 一个用户可以有多个角色。
- 一个菜单项可以被多个角色访问。
- 比较菜单项和子菜单项中提到的作用 用户角色数组。
下面给出了用户角色数组和导航项数组。
基本上,我想通过将其与用户角色进行比较来减少导航项数组。
用户角色数组:
["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']))