I am doing something wrong but cannot find exact solution for this issue.
I have a router with a view component A
:
const routes: Routes = [
{ path: '', redirectTo: '/list', pathMatch: 'full' },
{ path: 'list', component: ListComponent },
{ path: 'a/:id/:version', component: AComponent, resolve: { a: DataResolver}, runGuardsAndResolvers: 'always' }
];
Everything is working fine - I am navigating to component A
like /a/1/v1
- everything is initialized perfectly.
THE PROBLEM: there is a functionality that component is loading other versions of the view's content and I would expect that if I just click <a routerLink="/a/1/v2">load version 2</a>
somewhere from within A
component's view, the view is regenerated.
actually what happens is
ngOnInit
is not calledthe funny thing is that if I configure /b/..
and assign it to the same A
component in router's configuration, everything works as expected after navigating from /a/1/v1
to /b/1/v2
.
const routes: Routes = [
{ path: '', redirectTo: '/list', pathMatch: 'full' },
{ path: 'list', component: ListComponent },
{ path: 'a/:id/:version', component: AComponent, resolve: { a: DataResolver}, runGuardsAndResolvers: 'always' },
{ path: 'b/:id/:version', component: AComponent, resolve: { a: DataResolver}, runGuardsAndResolvers: 'always' },
];
I am a bit lost. Thanks for your help.
The reason the constructor and ngOnInit
is not called upon navigating to your component stems from Angular's default RouteReuseStrategy.
This base route reuse strategy only reuses routes when the matched router configs are identical. This prevents components from being destroyed and recreated when just the fragment or query parameters change (that is, the existing component is reused).
In other words, because only the fragment of your URL changed, /a/1/v1
-> /a/1/v2
, Angular tries to be smart and reuse the component. This prevents the constructor and ngOnInit
from being called again. (I know, infuriating, right?)
There are a couple of solutions I can think of.
ngOnInit
into the subscribe.class AComponent implements OnInit {
constructor(private _route: ActivatedRoute) {}
ngOnInit(): void {
this._route.params.subscribe(newParams => {
// handle any initialization logic here.
});
}
}
export class MyCustomRouteReuseStrategy implements RouteReuseStrategy {
// Never reuse a component!
shouldReuseRoute(): boolean {
return false;
}
// Implement the other default methods. Keep same functionality.
shouldDetach(): boolean { return false; }
store(): void {}
shouldAttach(): boolean { return false; }
retrieve(): DetachedRouteHandle | null { return null; }
}
// app.module.ts
@NgModule({
providers: [
{ provide: RouteReuseStrategy, useClass: MyCustomRouteReuseStrategy },
]