From 6e0efb37fcdea877b34d0c57bd80e69c64364f86 Mon Sep 17 00:00:00 2001 From: Mustafa Daglioglu Date: Thu, 28 Mar 2024 01:34:50 +0300 Subject: [PATCH 1/6] Add disable filtering with id in AbstractTreeService, delete function --- docs/en/UI/Angular/Modifying-the-Menu.md | 20 ++- .../core/src/lib/services/routes.service.ts | 59 ++++++-- .../core/src/lib/tests/routes.service.spec.ts | 136 ++++++++++++++++++ 3 files changed, 204 insertions(+), 11 deletions(-) diff --git a/docs/en/UI/Angular/Modifying-the-Menu.md b/docs/en/UI/Angular/Modifying-the-Menu.md index c59ce0d650..78733ef658 100644 --- a/docs/en/UI/Angular/Modifying-the-Menu.md +++ b/docs/en/UI/Angular/Modifying-the-Menu.md @@ -152,6 +152,21 @@ import { APP_ROUTE_PROVIDER } from './route.provider'; export class AppModule {} ``` +**Note:** +Route items's `name` property is must be a unique key. If there are multiple items with the same name, the last one will be displayed in the menu. If you want to display multiple items with the same name, you can call the `disableFiltering` method of the `RoutesService` to disable the filtering. + +```typescript +import { RoutesService } from '@abp/ng.core'; +import { Component } from '@angular/core'; + +@Component(/* component metadata */) +export class AppComponent { + constructor(private routes: RoutesService) { + routes.disableFiltering(); + } +} +``` + Here is what every property works as: - `path` is the absolute path of the navigation element. @@ -226,7 +241,7 @@ After adding the `routes` property as described above, the navigation menu looks ## How to Patch or Remove a Navigation Element -The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. +The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. Also you can use `delete` method to delete the routes with given properties. ```js // this.routes is instance of RoutesService @@ -249,6 +264,9 @@ const newHomeRouteConfig: Partial = { this.routes.add([dashboardRouteConfig]); this.routes.patch('::Menu:Home', newHomeRouteConfig); this.routes.remove(['Your navigation']); + +// or +this.routes.delete({ name: 'Your navigation' }); ``` - Moved the _Home_ navigation under the _Administration_ dropdown based on given `parentName`. diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts index c3a1ffe07f..8faab8cedf 100644 --- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts @@ -26,6 +26,7 @@ export abstract class AbstractTreeService[]>([]); protected othersGroup: string; + private filterRoutesEnabled = true; get flat(): T[] { return this._flat$.value; @@ -90,16 +91,54 @@ export abstract class AbstractTreeService(); - items.forEach(item => map.set(item[this.id], item)); + if (this.filterRoutesEnabled) { + const map = new Map(); + items.forEach(item => map.set(item[this.id], item)); + + const flatItems = this.filterWith(map); + map.forEach(pushValueTo(flatItems)); + + flatItems.sort(this.sort); + const visibleItems = flatItems.filter(item => !this.hide(item)); + return this.publish(flatItems, visibleItems); + } else { + const flatItems = this.flat.concat(items); + flatItems.sort(this.sort); + const visibleItems = flatItems.filter(item => !this.hide(item)); + return this.publish(flatItems, visibleItems); + } + } - const flatItems = this.filterWith(map); - map.forEach(pushValueTo(flatItems)); + delete(params: Partial): T[] { + const willRemoveItems = this.flat.filter(item => { + const keys = Object.keys(params) as Array>; + const isValid = keys.every(key => item[key] === params[key]); - flatItems.sort(this.sort); - const visibleItems = flatItems.filter(item => !this.hide(item)); + return isValid; + }); - return this.publish(flatItems, visibleItems); + if (willRemoveItems?.length) { + willRemoveItems.forEach(item => { + this.delete({ + [this.parentId]: item[this.id], + } as Partial); + }); + + const flatItems = this.flat.filter(item => !willRemoveItems.includes(item)); + const visibleItems = flatItems.filter(item => !this.hide(item)); + + return this.publish(flatItems, visibleItems); + } + + return this.flat; + } + + disableFiltering(): void { + this.filterRoutesEnabled = false; + } + + enableFiltering(): void { + this.filterRoutesEnabled = true; } find(predicate: (item: TreeNode) => boolean, tree = this.tree): TreeNode | null { @@ -145,8 +184,8 @@ export abstract class AbstractTreeService node[key] === params[key]) - ? node - : this.search(params, node.children), + ? node + : this.search(params, node.children), null, ); } @@ -164,7 +203,7 @@ export abstract class AbstractNavTreeService readonly parentId = 'parentName'; readonly hide = (item: T) => item.invisible || !this.isGranted(item); readonly sort = (a: T, b: T) => { - return this.compareFunc(a,b) + return this.compareFunc(a, b); }; constructor(protected injector: Injector) { diff --git a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts index 718b1fc0e2..0c993606b4 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts @@ -172,6 +172,66 @@ describe('Routes Service', () => { }); }); + describe('#disableFiltering', () => { + it('should allow to duplicate routes', () => { + service.disableFiltering(); + + service.add(routes); + + const flat = service.flat; + + expect(flat.length).toBe(routes.length); + }); + + it('should allow to duplicate routes with the same name', () => { + service.disableFiltering(); + + service.add([...routes, { path: '/foo/bar/test', name: 'bar', parentName: 'foo', order: 2 }]); + + const flat = service.flat; + + expect(flat.length).toBe(routes.length + 1); + }); + + it('should allow to routes with the same name but different parentName', () => { + service.disableFiltering(); + + service.add([ + { path: '/foo/bar', name: 'bar', parentName: 'foo', order: 2 }, + { path: '/foo/bar', name: 'bar', parentName: 'baz', order: 1 }, + ]); + + const flat = service.flat; + + expect(flat.length).toBe(2); + }); + }); + + describe('#enableFiltering', () => { + it('should not allow to duplicate routes', () => { + service.disableFiltering(); + + service.add(routes); + + service.enableFiltering(); + + service.add(routes); + + const flat = service.flat; + + expect(flat.length).toBe(5); + }); + + it('should not allow to duplicate routes with the same name', () => { + service.enableFiltering(); + service.add([...routes, { path: '/foo/bar/test', name: 'bar', parentName: 'any', order: 2 }]); + + const flat = service.flat; + + expect(flat.length).toBe(5); + }); + }); + describe('#find', () => { it('should return node found based on query', () => { service.add(routes); @@ -242,6 +302,82 @@ describe('Routes Service', () => { }); }); + describe('#delete', () => { + it('should remove route based on given route', () => { + service.add(routes); + + service.delete({ + name: 'bar', + parentName: 'foo', + }); + + const flat = service.flat; + + expect(flat.length).toBe(2); + + const notFound = service.find(route => route.name === 'bar'); + + expect(notFound).toBe(null); + }); + + it('should remove if more than one route has the same properties', () => { + service.disableFiltering(); + + service.add([ + ...routes, + { + path: '/foo/bar', + name: 'bar', + parentName: 'foo', + invisible: true, + order: 2, + breadcrumbText: 'Bar Breadcrumb', + }, + ]); + + service.delete({ + path: '/foo/bar', + name: 'bar', + parentName: 'foo', + invisible: true, + order: 2, + breadcrumbText: 'Bar Breadcrumb', + }); + + const flat = service.flat; + console.log(flat); + expect(flat.length).toBe(5); + + const notFound = service.search({ + path: '/foo/bar', + name: 'bar', + parentName: 'foo', + invisible: true, + order: 2, + breadcrumbText: 'Bar Breadcrumb', + }); + expect(notFound).toBe(null); + }); + + it("shouldn't remove if there is no route with the given properties", () => { + service.add(routes); + const flatLengthBeforeRemove = service.flat.length; + + service.delete({ + name: 'bar', + parentName: 'baz', + }); + + const flat = service.flat; + + expect(flatLengthBeforeRemove - flat.length).toBe(0); + + const notFound = service.find(route => route.name === 'bar'); + + expect(notFound).not.toBe(null); + }); + }); + describe('#patch', () => { it('should patch propeties of routes based on given routeNames', () => { service['isGranted'] = jest.fn(route => route.requiredPolicy !== 'X'); From 1fba624d56f115cbbb7abe438abccb9eb3ce2ad1 Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masumulu28@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:56:07 +0300 Subject: [PATCH 2/6] remove: `visibleItems` parameter from publish method and write hide logic inside of it --- .../core/src/lib/services/routes.service.ts | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts index 8faab8cedf..f1c2327684 100644 --- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts @@ -83,10 +83,10 @@ export abstract class AbstractTreeService !this.hide(item)))); return flatItems; } @@ -99,13 +99,11 @@ export abstract class AbstractTreeService !this.hide(item)); - return this.publish(flatItems, visibleItems); + return this.publish(flatItems); } else { const flatItems = this.flat.concat(items); flatItems.sort(this.sort); - const visibleItems = flatItems.filter(item => !this.hide(item)); - return this.publish(flatItems, visibleItems); + return this.publish(flatItems); } } @@ -125,9 +123,7 @@ export abstract class AbstractTreeService !willRemoveItems.includes(item)); - const visibleItems = flatItems.filter(item => !this.hide(item)); - - return this.publish(flatItems, visibleItems); + return this.publish(flatItems); } return this.flat; @@ -156,9 +152,7 @@ export abstract class AbstractTreeService !this.hide(item)); - - return this.publish(flatItems, visibleItems); + return this.publish(flatItems); } refresh(): T[] { @@ -171,9 +165,7 @@ export abstract class AbstractTreeService !this.hide(item)); - - return this.publish(flatItems, visibleItems); + return this.publish(flatItems); } search(params: Partial, tree = this.tree): TreeNode | null { From bb31f3238ce4599107b3bfbfa7d06364763b5d72 Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masumulu28@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:08:02 +0300 Subject: [PATCH 3/6] re-order and refactor methods --- .../core/src/lib/services/routes.service.ts | 82 +++++++++++-------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts index f1c2327684..4c1cae7e39 100644 --- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts @@ -52,31 +52,16 @@ export abstract class AbstractTreeService[] { - return createTreeFromList>( - items, - item => item[this.id], - item => item[this.parentId], - item => BaseTreeNode.create(item), - ); - } - - protected createGroupedTree(list: TreeNode[]): RouteGroup[] | undefined { - const map = createGroupMap(list, this.othersGroup); - if (!map) { - return undefined; - } - - return Array.from(map, ([key, items]) => ({ group: key, items })); - } - private filterWith(setOrMap: Set | Map): T[] { return this._flat$.value.filter(item => !setOrMap.has(item[this.id])); } private findItemsToRemove(set: Set): Set { return this._flat$.value.reduce((acc, item) => { - if (!acc.has(item[this.parentId])) return acc; + if (!acc.has(item[this.parentId])) { + return acc; + } + const childSet = new Set([item[this.id]]); const children = this.findItemsToRemove(childSet); return new Set([...acc, ...children]); @@ -90,6 +75,24 @@ export abstract class AbstractTreeService[] { + return createTreeFromList>( + items, + item => item[this.id], + item => item[this.parentId], + item => BaseTreeNode.create(item), + ); + } + + protected createGroupedTree(list: TreeNode[]): RouteGroup[] | undefined { + const map = createGroupMap(list, this.othersGroup); + if (!map) { + return undefined; + } + + return Array.from(map, ([key, items]) => ({ group: key, items })); + } + add(items: T[]): T[] { if (this.filterRoutesEnabled) { const map = new Map(); @@ -137,17 +140,26 @@ export abstract class AbstractTreeService) => boolean, tree = this.tree): TreeNode | null { - return tree.reduce | null>( - (acc, node) => (acc ? acc : predicate(node) ? node : this.find(predicate, node.children)), - null, - ); + find(predicate: (item: TreeNode) => boolean, tree = this.tree): TreeNode | null { + return tree.reduce | null>((acc, node) => { + if (acc) { + return acc; + } + + if (predicate(node)) { + return node; + } + + return this.find(predicate, node.children); + }, null); } patch(identifier: string, props: Partial): T[] | false { const flatItems = this._flat$.value; const index = flatItems.findIndex(item => item[this.id] === identifier); - if (index < 0) return false; + if (index < 0) { + return false; + } flatItems[index] = { ...flatItems[index], ...props }; @@ -171,15 +183,17 @@ export abstract class AbstractTreeService, tree = this.tree): TreeNode | null { const searchKeys = Object.keys(params) as Array>; - return tree.reduce | null>( - (acc, node) => - acc - ? acc - : searchKeys.every(key => node[key] === params[key]) - ? node - : this.search(params, node.children), - null, - ); + return tree.reduce | null>((acc, node) => { + if (acc) { + return acc; + } + + if (searchKeys.every(key => node.item[key] === params[key])) { + return node; + } + + return this.search(params, node.children); + }, null); } } From 9ebfe62ee7aa0330a17e2fedbd63ce59beb0d114 Mon Sep 17 00:00:00 2001 From: Mustafa Daglioglu Date: Tue, 23 Apr 2024 14:26:02 +0300 Subject: [PATCH 4/6] Change method and property names in the routes.service.ts --- docs/en/UI/Angular/Modifying-the-Menu.md | 8 +- .../core/src/lib/services/routes.service.ts | 81 +++++++++---------- .../core/src/lib/tests/routes.service.spec.ts | 37 ++++----- 3 files changed, 61 insertions(+), 65 deletions(-) diff --git a/docs/en/UI/Angular/Modifying-the-Menu.md b/docs/en/UI/Angular/Modifying-the-Menu.md index 78733ef658..dba2c9be91 100644 --- a/docs/en/UI/Angular/Modifying-the-Menu.md +++ b/docs/en/UI/Angular/Modifying-the-Menu.md @@ -153,7 +153,7 @@ export class AppModule {} ``` **Note:** -Route items's `name` property is must be a unique key. If there are multiple items with the same name, the last one will be displayed in the menu. If you want to display multiple items with the same name, you can call the `disableFiltering` method of the `RoutesService` to disable the filtering. +Route items's `name` property is must be a unique key. If there are multiple items with the same name, the last one will be displayed in the menu. If you want to display multiple items with the same name, you can call the `setSingularizeStatus(false)` method of the `RoutesService` to disable the singularization of the names. This method should be called before adding the routes. If you want to enable the singularization of the names, you can call the `setSingularizeStatus(true)` method of the `RoutesService` to enable the singularization of the names. This method should be called before adding the routes. The default value of the singularization status is `true`. The default value of the singularization status is `true`. ```typescript import { RoutesService } from '@abp/ng.core'; @@ -162,7 +162,7 @@ import { Component } from '@angular/core'; @Component(/* component metadata */) export class AppComponent { constructor(private routes: RoutesService) { - routes.disableFiltering(); + routes.setSingularizeStatus(false); } } ``` @@ -241,7 +241,7 @@ After adding the `routes` property as described above, the navigation menu looks ## How to Patch or Remove a Navigation Element -The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. Also you can use `delete` method to delete the routes with given properties. +The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. Also you can use `removeByParams` method to delete the routes with given properties. ```js // this.routes is instance of RoutesService @@ -266,7 +266,7 @@ this.routes.patch('::Menu:Home', newHomeRouteConfig); this.routes.remove(['Your navigation']); // or -this.routes.delete({ name: 'Your navigation' }); +this.routes.removeByParams({ name: 'Your navigation' }); ``` - Moved the _Home_ navigation under the _Administration_ dropdown based on given `parentName`. diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts index 4c1cae7e39..6837e57aca 100644 --- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts @@ -26,7 +26,7 @@ export abstract class AbstractTreeService[]>([]); protected othersGroup: string; - private filterRoutesEnabled = true; + protected shouldSingularizeRoutes = true; get flat(): T[] { return this._flat$.value; @@ -94,53 +94,25 @@ export abstract class AbstractTreeService(); - items.forEach(item => map.set(item[this.id], item)); - - const flatItems = this.filterWith(map); - map.forEach(pushValueTo(flatItems)); + let flatItems: T[] = []; - flatItems.sort(this.sort); - return this.publish(flatItems); - } else { - const flatItems = this.flat.concat(items); - flatItems.sort(this.sort); - return this.publish(flatItems); + if (!this.shouldSingularizeRoutes) { + flatItems = [...this.flat, ...items]; } - } - - delete(params: Partial): T[] { - const willRemoveItems = this.flat.filter(item => { - const keys = Object.keys(params) as Array>; - const isValid = keys.every(key => item[key] === params[key]); - - return isValid; - }); - - if (willRemoveItems?.length) { - willRemoveItems.forEach(item => { - this.delete({ - [this.parentId]: item[this.id], - } as Partial); - }); - const flatItems = this.flat.filter(item => !willRemoveItems.includes(item)); - return this.publish(flatItems); + if (this.shouldSingularizeRoutes) { + const map = new Map(); + items.forEach(item => map.set(item[this.id], item)); + flatItems = this.filterWith(map); + map.forEach(pushValueTo(flatItems)); } - return this.flat; - } - - disableFiltering(): void { - this.filterRoutesEnabled = false; - } + flatItems.sort(this.sort); - enableFiltering(): void { - this.filterRoutesEnabled = true; + return this.publish(flatItems); } - find(predicate: (item: TreeNode) => boolean, tree = this.tree): TreeNode | null { + find(predicate: (item: TreeNode) => boolean, tree = this.tree): TreeNode | null { return tree.reduce | null>((acc, node) => { if (acc) { return acc; @@ -180,6 +152,29 @@ export abstract class AbstractTreeService): T[] | null { + if (!params) { + return null; + } + + const keys = Object.keys(params) as Array>; + if (keys.length === 0) { + return null; + } + + const excludedList = this.flat.filter(item => keys.every(key => item[key] === params[key])); + if (!excludedList?.length) { + return null; + } + + for (const item of excludedList) { + this.removeByParams({ [this.parentId]: item[this.id] } as Partial); + } + + const flatItems = this.flat.filter(item => !excludedList.includes(item)); + return this.publish(flatItems); + } + search(params: Partial, tree = this.tree): TreeNode | null { const searchKeys = Object.keys(params) as Array>; @@ -188,13 +183,17 @@ export abstract class AbstractTreeService node.item[key] === params[key])) { + if (searchKeys.every(key => node[key] === params[key])) { return node; } return this.search(params, node.children); }, null); } + + setSingularizeStatus(singularize = true): void { + this.shouldSingularizeRoutes = singularize; + } } @Injectable() diff --git a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts index 0c993606b4..a751b84d6d 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts @@ -172,9 +172,9 @@ describe('Routes Service', () => { }); }); - describe('#disableFiltering', () => { - it('should allow to duplicate routes', () => { - service.disableFiltering(); + describe('#setSingularizeStatus', () => { + it('should allow to duplicate routes when called with false', () => { + service.setSingularizeStatus(false); service.add(routes); @@ -183,8 +183,8 @@ describe('Routes Service', () => { expect(flat.length).toBe(routes.length); }); - it('should allow to duplicate routes with the same name', () => { - service.disableFiltering(); + it('should allow to duplicate routes with the same name when called with false', () => { + service.setSingularizeStatus(false); service.add([...routes, { path: '/foo/bar/test', name: 'bar', parentName: 'foo', order: 2 }]); @@ -193,8 +193,8 @@ describe('Routes Service', () => { expect(flat.length).toBe(routes.length + 1); }); - it('should allow to routes with the same name but different parentName', () => { - service.disableFiltering(); + it('should allow to routes with the same name but different parentName when called with false', () => { + service.setSingularizeStatus(false); service.add([ { path: '/foo/bar', name: 'bar', parentName: 'foo', order: 2 }, @@ -205,15 +205,13 @@ describe('Routes Service', () => { expect(flat.length).toBe(2); }); - }); - describe('#enableFiltering', () => { - it('should not allow to duplicate routes', () => { - service.disableFiltering(); + it('should not allow to duplicate routes when called with true', () => { + service.setSingularizeStatus(false); service.add(routes); - service.enableFiltering(); + service.setSingularizeStatus(true); service.add(routes); @@ -222,8 +220,8 @@ describe('Routes Service', () => { expect(flat.length).toBe(5); }); - it('should not allow to duplicate routes with the same name', () => { - service.enableFiltering(); + it('should not allow to duplicate routes with the same name when called with true', () => { + service.setSingularizeStatus(true); service.add([...routes, { path: '/foo/bar/test', name: 'bar', parentName: 'any', order: 2 }]); const flat = service.flat; @@ -302,11 +300,11 @@ describe('Routes Service', () => { }); }); - describe('#delete', () => { + describe('#removeByParams', () => { it('should remove route based on given route', () => { service.add(routes); - service.delete({ + service.removeByParams({ name: 'bar', parentName: 'foo', }); @@ -321,7 +319,7 @@ describe('Routes Service', () => { }); it('should remove if more than one route has the same properties', () => { - service.disableFiltering(); + service.setSingularizeStatus(false); service.add([ ...routes, @@ -335,7 +333,7 @@ describe('Routes Service', () => { }, ]); - service.delete({ + service.removeByParams({ path: '/foo/bar', name: 'bar', parentName: 'foo', @@ -345,7 +343,6 @@ describe('Routes Service', () => { }); const flat = service.flat; - console.log(flat); expect(flat.length).toBe(5); const notFound = service.search({ @@ -363,7 +360,7 @@ describe('Routes Service', () => { service.add(routes); const flatLengthBeforeRemove = service.flat.length; - service.delete({ + service.removeByParams({ name: 'bar', parentName: 'baz', }); From 27bac2c8626e61f93a52be07256e546690bb8243 Mon Sep 17 00:00:00 2001 From: Mustafa Daglioglu Date: Wed, 24 Apr 2024 09:47:03 +0300 Subject: [PATCH 5/6] Rename removeByParams method name to removeByParam --- docs/en/UI/Angular/Modifying-the-Menu.md | 4 ++-- .../packages/core/src/lib/services/routes.service.ts | 4 ++-- .../packages/core/src/lib/tests/routes.service.spec.ts | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/en/UI/Angular/Modifying-the-Menu.md b/docs/en/UI/Angular/Modifying-the-Menu.md index dba2c9be91..938d490e6f 100644 --- a/docs/en/UI/Angular/Modifying-the-Menu.md +++ b/docs/en/UI/Angular/Modifying-the-Menu.md @@ -241,7 +241,7 @@ After adding the `routes` property as described above, the navigation menu looks ## How to Patch or Remove a Navigation Element -The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. Also you can use `removeByParams` method to delete the routes with given properties. +The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. Also you can use `removeByParam` method to delete the routes with given properties. ```js // this.routes is instance of RoutesService @@ -266,7 +266,7 @@ this.routes.patch('::Menu:Home', newHomeRouteConfig); this.routes.remove(['Your navigation']); // or -this.routes.removeByParams({ name: 'Your navigation' }); +this.routes.removeByParam({ name: 'Your navigation' }); ``` - Moved the _Home_ navigation under the _Administration_ dropdown based on given `parentName`. diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts index 6837e57aca..393c724423 100644 --- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts @@ -152,7 +152,7 @@ export abstract class AbstractTreeService): T[] | null { + removeByParam(params: Partial): T[] | null { if (!params) { return null; } @@ -168,7 +168,7 @@ export abstract class AbstractTreeService); + this.removeByParam({ [this.parentId]: item[this.id] } as Partial); } const flatItems = this.flat.filter(item => !excludedList.includes(item)); diff --git a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts index a751b84d6d..affd15e873 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts @@ -300,11 +300,11 @@ describe('Routes Service', () => { }); }); - describe('#removeByParams', () => { + describe('#removeByParam', () => { it('should remove route based on given route', () => { service.add(routes); - service.removeByParams({ + service.removeByParam({ name: 'bar', parentName: 'foo', }); @@ -333,7 +333,7 @@ describe('Routes Service', () => { }, ]); - service.removeByParams({ + service.removeByParam({ path: '/foo/bar', name: 'bar', parentName: 'foo', @@ -360,7 +360,7 @@ describe('Routes Service', () => { service.add(routes); const flatLengthBeforeRemove = service.flat.length; - service.removeByParams({ + service.removeByParam({ name: 'bar', parentName: 'baz', }); From 5ff7008634fb3331edafc7d249b10cbee780e99f Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masumulu28@users.noreply.github.com> Date: Wed, 24 Apr 2024 15:23:43 +0300 Subject: [PATCH 6/6] Update Modifying-the-Menu.md --- docs/en/UI/Angular/Modifying-the-Menu.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/en/UI/Angular/Modifying-the-Menu.md b/docs/en/UI/Angular/Modifying-the-Menu.md index 938d490e6f..7a9c9a1004 100644 --- a/docs/en/UI/Angular/Modifying-the-Menu.md +++ b/docs/en/UI/Angular/Modifying-the-Menu.md @@ -152,8 +152,11 @@ import { APP_ROUTE_PROVIDER } from './route.provider'; export class AppModule {} ``` -**Note:** -Route items's `name` property is must be a unique key. If there are multiple items with the same name, the last one will be displayed in the menu. If you want to display multiple items with the same name, you can call the `setSingularizeStatus(false)` method of the `RoutesService` to disable the singularization of the names. This method should be called before adding the routes. If you want to enable the singularization of the names, you can call the `setSingularizeStatus(true)` method of the `RoutesService` to enable the singularization of the names. This method should be called before adding the routes. The default value of the singularization status is `true`. The default value of the singularization status is `true`. +### Singularize Route Item +- `name` property is must be a unique key. If there are multiple items with the same name, the last one will be displayed in the menu. +- If you want to display multiple items in different parent with the same name, you can call the **setSingularizeStatus(false)** method of the `RoutesService` to disable the singularization. + - **This method should be called before adding the routes.** +- To enable the singularization of the names, you can call the **setSingularizeStatus(true) `(default value: true)`** method of the `RoutesService`. ```typescript import { RoutesService } from '@abp/ng.core';