diff --git a/src/core/classes/page-items-list-manager.ts b/src/core/classes/page-items-list-manager.ts index b2025e104..11089a807 100644 --- a/src/core/classes/page-items-list-manager.ts +++ b/src/core/classes/page-items-list-manager.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ActivatedRouteSnapshot, Params, UrlSegment } from '@angular/router'; +import { ActivatedRoute, ActivatedRouteSnapshot, Params, UrlSegment } from '@angular/router'; import { Subscription } from 'rxjs'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; @@ -29,12 +29,12 @@ export abstract class CorePageItemsListManager { protected itemsMap: Record | null = null; protected hasMoreItems = true; protected selectedItem: Item | null = null; - protected pageComponent: unknown; + protected pageRouteLocator?: unknown | ActivatedRoute; protected splitView?: CoreSplitViewComponent; protected splitViewOutletSubscription?: Subscription; - constructor(pageComponent: unknown) { - this.pageComponent = pageComponent; + constructor(pageRouteLocator: unknown | ActivatedRoute) { + this.pageRouteLocator = pageRouteLocator; } get items(): Item[] { @@ -62,7 +62,7 @@ export abstract class CorePageItemsListManager { this.watchSplitViewOutlet(splitView); // Calculate current selected item. - const route = CoreNavigator.getCurrentRoute({ pageComponent: this.pageComponent }); + const route = this.getCurrentPageRoute(); this.updateSelectedItem(route?.snapshot ?? null); // Select default item if none is selected on a non-mobile layout. @@ -138,7 +138,7 @@ export abstract class CorePageItemsListManager { */ async select(item: Item): Promise { // Get current route in the page. - const route = CoreNavigator.getCurrentRoute({ pageComponent: this.pageComponent }); + const route = this.getCurrentPageRoute(); if (route === null) { return; @@ -208,7 +208,7 @@ export abstract class CorePageItemsListManager { return false; } - return !this.splitView?.isNested; + return !!this.splitView && !this.splitView?.isNested; } /** @@ -253,6 +253,19 @@ export abstract class CorePageItemsListManager { return segments.map(segment => segment.path).join('/').replace(/\/+/, '/').trim() || null; } + /** + * Get page route. + * + * @returns Current page route, if any. + */ + private getCurrentPageRoute(): ActivatedRoute | null { + if (this.pageRouteLocator instanceof ActivatedRoute) { + return CoreNavigator.isRouteActive(this.pageRouteLocator) ? this.pageRouteLocator : null; + } + + return CoreNavigator.getCurrentRoute({ pageComponent: this.pageRouteLocator }); + } + /** * Get the page route given a child route on the splitview outlet. * @@ -260,11 +273,28 @@ export abstract class CorePageItemsListManager { * @return Page route. */ private getPageRouteFromSplitViewOutlet(route: ActivatedRouteSnapshot | null): ActivatedRouteSnapshot | null { - while (route && route.component !== this.pageComponent) { + const isPageRoute = this.buildRouteMatcher(); + + while (route && !isPageRoute(route)) { route = route.parent; } return route; } + /** + * Build a function to check whether the given snapshot belongs to the page. + * + * @returns Route matcher. + */ + private buildRouteMatcher(): (route: ActivatedRouteSnapshot) => boolean { + if (this.pageRouteLocator instanceof ActivatedRoute) { + const pageRoutePath = CoreNavigator.getRouteFullPath(this.pageRouteLocator.snapshot); + + return route => CoreNavigator.getRouteFullPath(route) === pageRoutePath; + } + + return route => route.component === this.pageRouteLocator; + } + } diff --git a/src/core/services/navigator.ts b/src/core/services/navigator.ts index a5cc68273..1b47f19ed 100644 --- a/src/core/services/navigator.ts +++ b/src/core/services/navigator.ts @@ -398,6 +398,27 @@ export class CoreNavigatorService { return pageComponent || routeData ? null : route; } + /** + * Check whether a route is active within the current stack. + * + * @param route Route to check. + * @return Whether the route is active or not. + */ + isRouteActive(route: ActivatedRoute): boolean { + const routePath = this.getRouteFullPath(route.snapshot); + let activeRoute: ActivatedRoute | null = Router.routerState.root; + + while (activeRoute) { + if (this.getRouteFullPath(activeRoute.snapshot) === routePath) { + return true; + } + + activeRoute = activeRoute.firstChild; + } + + return false; + } + /** * Increase the number of times a route is repeated on the navigation stack. *