I tried to use custom reuse strategy in my angular2 project, but I found it doesn't work with lazy module loading. Anyone who know about this? My project is angular 2.6.4
reuse-strategy.ts
import {RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle} from "@angular/router";
export class CustomReuseStrategy implements RouteReuseStrategy {
handlers: {[key: string]: DetachedRouteHandle} = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean {
console.debug('CustomReuseStrategy:shouldDetach', route);
return true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
console.debug('CustomReuseStrategy:store', route, handle);
this.handlers[route.routeConfig.path] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
console.debug('CustomReuseStrategy:shouldAttach', route);
return !!route.routeConfig && !!this.handlers[route.routeConfig.path];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
console.debug('CustomReuseStrategy:retrieve', route);
if (!route.routeConfig) return null;
return this.handlers[route.routeConfig.path];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
console.debug('CustomReuseStrategy:shouldReuseRoute', future, curr);
return future.routeConfig === curr.routeConfig;
}
}
app.module.ts
const appRoutes: Routes = [
{ path: 'crisis-center', component: CrisisListComponent },
{ path: 'heroes', loadChildren: 'app/hero-list.module#HeroListModule' },
{ path: '', redirectTo: '/crisis-center', pathMatch: 'full' }
];
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers:[
{provide: RouteReuseStrategy, useClass: CustomReuseStrategy}
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
and I put <input>
to both component and I tested it.
the value of input in CrisisListComponent
is stored but, the value of HeroListComponent lazy-loaded
is not preserved.
I don't know it's not supported yet. Thank you for helping me.
RouteReuseStrategy
does work with LazyLoaded components.
The problem here is that you're using route.routeConfig.path
as the key to store and retrieve the Handles.
I don't know why, but with LazyLoaded modules, route.routeConfig.path
is empty when executing shouldAttach
The solution I use is to define a custom key in my routes, like:
{ path: '...', loadChildren: '...module#...Module', data: { key: 'custom_key' } }
This key value can be easily accessed in the ActivatedRouteSnapshot
, like:
route.data.key
With this key you can store and retrieve the handles correctly.
Use this one. It use component name as the key to store and retrieve the Handles.
import {ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy} from '@angular/router';
export class CustomReuseStrategy implements RouteReuseStrategy {
handlers: { [key: string]: DetachedRouteHandle } = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
this.handlers[this.getKey(route)] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!route.routeConfig && !!this.handlers[this.getKey(route)];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
if (!route.routeConfig) {
return null;
}
return this.handlers[this.getKey(route)];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return curr.routeConfig === future.routeConfig;
}
private getKey(route: ActivatedRouteSnapshot) {
let key: string;
if (route.component) {
key = route.component['name'];
} else {
key = route.firstChild.component['name'];
}
return key;
}
}
To make it work you should take into account the full path instead of simple route.routeConfig.path as most articles suggests. For example:
private getKey(route: ActivatedRouteSnapshot): string {
return route.pathFromRoot
.map((el: ActivatedRouteSnapshot) => el.routeConfig ? el.routeConfig.path : '')
.filter(str => str.length > 0)
.join('');
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
this.handlers[this.getKey(route)] = handle;
}
use this ReuseStrategy
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router';
export class CustomReuseStrategy implements RouteReuseStrategy {
private handlers: {[key: string]: DetachedRouteHandle} = {};
constructor() {
}
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
this.handlers[route.url.join("/") || route.parent.url.join("/")] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!this.handlers[route.url.join("/") || route.parent.url.join("/")];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
return this.handlers[route.url.join("/") || route.parent.url.join("/")];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig;
}
}
use this custom Reuse Strategy file for lazy module loading
import { ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle } from '@angular/router';
/** Interface for object which can store both:
* An ActivatedRouteSnapshot, which is useful for determining whether or not you should attach a route (see this.shouldAttach)
* A DetachedRouteHandle, which is offered up by this.retrieve, in the case that you do want to attach the stored route
*/
interface RouteStorageObject {
snapshot: ActivatedRouteSnapshot;
handle: DetachedRouteHandle;
}
export class CustomReuseStrategy implements RouteReuseStrategy {
handlers: {[key: string]: DetachedRouteHandle} = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean {
console.debug('CustomReuseStrategy:shouldDetach', route);
return !!route.data && !!(route.data as any).shouldDetach;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
console.debug('CustomReuseStrategy:store', route, handle);
this.handlers[route.data['key']]= handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
console.debug('CustomReuseStrategy:shouldAttach', route);
return !!route.data && !!this.handlers[route.data['key']];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
console.debug('CustomReuseStrategy:retrieve', route);
if (!route.data) return null;
return this.handlers[route.data['key']];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
console.debug('CustomReuseStrategy:shouldReuseRoute', future, curr);
return future.data === curr.data;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With