From 4f58a6603e33e357b0cdadb1a34f4d0406d4a5de Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Sun, 26 Mar 2023 14:49:32 +0300 Subject: [PATCH] delete stored route when attached --- src/lib/utils/custom-route-reuse.strategy.ts | 61 ++++++++++++-------- tsconfig.json | 10 ++-- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/lib/utils/custom-route-reuse.strategy.ts b/src/lib/utils/custom-route-reuse.strategy.ts index 24cabff..00d69b7 100644 --- a/src/lib/utils/custom-route-reuse.strategy.ts +++ b/src/lib/utils/custom-route-reuse.strategy.ts @@ -1,5 +1,7 @@ import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'; import { Debounce } from '../utils'; +import { ComponentRef, Injectable } from '@angular/core'; +import { Subject } from 'rxjs'; export interface OnAttach { ngOnAttach(previousRoute?: ActivatedRouteSnapshot): void; @@ -9,13 +11,23 @@ export interface OnDetach { ngOnDetach(): void; } -interface RouteStorageObject { - handle: DetachedRouteHandle; - previousRoute: ActivatedRouteSnapshot; +export function getReusableRouteKey(route: ActivatedRouteSnapshot): string { + return route.pathFromRoot + .map((el: ActivatedRouteSnapshot) => (el.routeConfig ? `${el.routeConfig.path}${JSON.stringify(el.params)}` : '')) + .filter(str => str.length > 0) + .join(''); } +interface RouteStorageObject { + readonly handle: DetachedRouteHandle; + readonly previousRoute: ActivatedRouteSnapshot; +} + +@Injectable({ providedIn: 'root' }) export class CustomRouteReuseStrategy implements RouteReuseStrategy { - private _storedRoutes: { [key: string]: RouteStorageObject } = {}; + readonly attached$ = new Subject(); + readonly detached$ = new Subject(); + readonly #storedRoutes = new Map(); private static _removeTooltips(): void { while (document.getElementsByTagName('mat-tooltip-component').length > 0) { @@ -27,7 +39,7 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy { if (!route?.routeConfig?.data) { return false; } - return !!route.routeConfig.data['reuse'] && !!this._getKey(route); + return !!route.routeConfig.data['reuse'] && !!getReusableRouteKey(route); } store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { @@ -36,44 +48,45 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy { } CustomRouteReuseStrategy._removeTooltips(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const element: any = handle; + const element = <{ componentRef: ComponentRef } | undefined>handle; if (element?.componentRef?.instance?.ngOnDetach) { - this._onDetach(element.componentRef?.instance); + this._onDetach(element.componentRef.instance); } - this._storedRoutes[this._getKey(route)] = { + if (element) { + this.detached$.next(route); + } + + this.#storedRoutes.set(getReusableRouteKey(route), { handle: element as DetachedRouteHandle, previousRoute: route, - }; + }); } shouldAttach(route: ActivatedRouteSnapshot): boolean { - return !!this._storedRoutes[this._getKey(route)]; + return this.#storedRoutes.has(getReusableRouteKey(route)); } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { - const key = this._getKey(route); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const element: any = this._storedRoutes[key]?.handle; + const key = getReusableRouteKey(route); + const value = this.#storedRoutes.get(key); + const element = <{ componentRef: ComponentRef } | undefined>value?.handle; - if (element?.componentRef?.instance?.ngOnAttach) { - this._onAttach(element.componentRef?.instance, this._storedRoutes[key].previousRoute); + if (element?.componentRef?.instance.ngOnAttach && value) { + this._onAttach(element.componentRef.instance, value.previousRoute); + setTimeout(() => this.#storedRoutes.delete(key)); + } + + if (element) { + this.attached$.next(route); } return element as DetachedRouteHandle; } shouldReuseRoute(future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean { - return this._getKey(future) === this._getKey(current); - } - - private _getKey(route: ActivatedRouteSnapshot): string { - return route.pathFromRoot - .map((el: ActivatedRouteSnapshot) => (el.routeConfig ? `${el.routeConfig.path}${JSON.stringify(el.params)}` : '')) - .filter(str => str.length > 0) - .join(''); + return getReusableRouteKey(future) === getReusableRouteKey(current); } @Debounce() diff --git a/tsconfig.json b/tsconfig.json index d76b45e..0ff4633 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,5 @@ { + "compileOnSave": false, "compilerOptions": { "outDir": "../../dist/out-tsc", "strict": true, @@ -12,16 +13,15 @@ "sourceMap": true, "downlevelIteration": true, "experimentalDecorators": true, - "noImplicitAny": true, "moduleResolution": "node", "importHelpers": true, "resolveJsonModule": true, - "target": "es2021", - "module": "es2020", - "lib": ["es2021", "dom"], + "target": "ES2022", + "module": "ES2022", + "lib": ["ES2022", "dom"], "allowSyntheticDefaultImports": true }, - "include": ["src/**/*.ts"], + "include": ["./**/*"], "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true,