here's my lazy loaded child module:
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(acnpRoutes),
....
],
declarations: [...],
providers: [
{provide: RouteReuseStrategy, useClass: ACNPReuseStrategy}
]
})
export class AddCustomerNaturalPersonModule {
}
routes:
const acnpRoutes: Routes = [
{
path: '',
component: AddCustomerNaturalPersonComponent,
children: [
{
path: 'stepOne',
component: ACNPStepOneComponent
},
{
path: 'stepTwo',
component: ACNPStepTwoComponent
},
]
}
]
And ACPNReuseStrategy:
export class ACNPReuseStrategy implements RouteReuseStrategy {
handlers: {[key: string]: DetachedRouteHandle} = {}
shouldDetach(route: ActivatedRouteSnapshot): boolean {
console.log(1)
return true;
}
store(route: ActivatedRouteSnapshot, handle: {}): void {
console.log(2)
}
...
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
console.log(5)
}
}
Unfortunately, none of these console.logs in ACNPReuseStrategy methods is fired. Why is that? Is reusing components possible in lazy loaded module?
TL;DR provide your RouteReuseStrategy
in main module instead of child module (app.module.ts
by default). Then, assign each route a key
in route.data
to differentiate your routes.
I also encountered this issue recently. My child module is mounted under the main app routes like this:
..., { // in app.route.ts
path: 'apimarket',
canActivate: [DeveloperResolve],
loadChildren: './apimarket/apimarket.module#ApiMarketModule'
}
If I provide my customized RouteReuseStrategy
in the child module ApiMarketModule
, the RouteReuseStrategy
will never be constructed.
The solution is to provide your Strategy in main module instead of child module (app.module.ts
in my case). Then your RouteReuseStrategy
will be constructed correctly.
However, the Strategy won't work as expected due to route.routeConfig.path
is relative path because of your sub routes. To fix this, my solution is assign a unique key
to my routes like this:
export const apimarketRoutes: Routes = [
{
path: '',
component: ApiMarketComponent,
data: {
shouldReuse: true,
key: 'apimarketroot'
}
},
{
path: ':id',
component: ContentPageComponent,
}
];
Here is my RouteReuseStrategy
implementation FYR
export class MyRouteReuseStrategy implements RouteReuseStrategy {
handlers: {[key: string]: DetachedRouteHandle} = {};
constructor() {
console.log('constructed');
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
if (!route.data['shouldReuse']) {
return null;
}
console.log('Attach cached page for: ', route.data['key']);
return this.handlers[route.data['key']];
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
if (route.data['shouldReuse']) {
this.handlers[route.data['key']] = handle;
}
}
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return !!route.data['shouldReuse'];
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!route.data['shouldReuse'] && !!this.handlers[route.data['key']];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
return !!future.data['shouldReuse'];
}
}
(RouteReuseStrategy
isn't well documented, my solution may have potential performance issue due to the strategy working on root level. Welcome to discuss :) )
firstly,you must understand what are future and curr.eg: when you navigate from 127.0.0.1:4200/a to 127.0.0.1:4200/b and now you are in b. the future is 127.0.0.1:4200/a ,curr is b,because the future means that you will come back in the future.
when shouldReuseRoute return false ,future !== curr. that is to say the future is different from the curr,we need reuse the future in the future,then,the future will be detach , store and waiting to be reused. On the contrary, when it returns true, nothing is done because the future is the same as the curr.Imagine when you're in a, you want to go b,a is the future,b is the curr.A and b is the same thing, what is necessary to reuse, detach, store a?
Last,You have to understand the order in which these five methods are executed. eg:
navigate to a
shouldReuseRoute->return true->do nothing
a->b
shouldReuseRoute()->return false->shouldDetach()->return true->store a
then b->a
shouldReuseRoute()->return false->shouldDetach()->return true->store b->retrieve() return a ->attach() a.
Be careful,when b->a,after shouldReuseRoute() return false,These methods are not strictly in the order above. For you to more easily understand this process, I deliberately writed so.But you still follow the above order to understand, this does not have any effect.
For better understanding, you should look at these examples. One of the examples will involve lazy loading.
https://medium.com/@gerasimov.pk/how-to-reuse-rendered-component-in-angular-2-3-with-routereusestrategy-64628e1ca3eb
How to implement RouteReuseStrategy shouldDetach for specific routes in Angular 2
My English is not good,I hope you can understand what I said.
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