Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RouteReuseStrategy not working for routing with dynamic params

router-strategy.ts

import {RouteReuseStrategy,ActivatedRouteSnapshot,DetachedRouteHandle,} from '@angular/router';

export class RtgRouteReuseStrategy implements RouteReuseStrategy {
  private routeLeftFrom: string | undefined;
  private handlers: { [key: string]: DetachedRouteHandle } = {};

  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    this.routeLeftFrom = route.routeConfig!.path;
    return route.data['shouldReuseRoute'] || false;
  }

  store(route: ActivatedRouteSnapshot, handler: DetachedRouteHandle): void {
    if (handler) {
      this.handlers[this.getUrl(route)] = handler;
    }
  }

  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    const url = this.getUrl(route);
    return !!this.handlers[url];
  }

  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
    if (!route.routeConfig || route.routeConfig.loadChildren) {
      return null;
    }

    return this.handlers[this.getUrl(route)];
  }

  shouldReuseRoute(future: ActivatedRouteSnapshot,current: ActivatedRouteSnapshot): boolean {
    const reUseUrl = future.routeConfig?.data?.['reuse'];
    const defaultReuse = future.routeConfig === current.routeConfig;
    return reUseUrl || defaultReuse;
  }

  getUrl(route: ActivatedRouteSnapshot): string {
    const url = route.url.map((segment) => segment.path).join('/');
    return url;
  }
}

app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { AuthGuard } from './core/authguard/auth.guard';
import { RtgCreationComponent } from './modules/rtg-form/components/rtg-creation/rtg-creation.component';
import { RtgViewComponent } from './modules/rtg-form/components/rtg-view/rtg-view.component';

const routes: Routes = [
  { path: '', redirectTo: "rtgmaster", pathMatch: "full" },
  {
    path: "rtgmaster",
    canActivate: [AuthGuard],
    component: AppComponent
  },
  {
    path:"form/:rtgId/:email/:phnNumber",
    canActivate: [AuthGuard],
    component:RtgCreationComponent,
     data: {
        shouldReuseRoute: true,
        reuseRoutesFrom: ["rtgmaster","form/:rtgId/:email/:phnNumber/view"]
     }
  },
  {
    path: "form/:rtgId/:email/:phnNumber/view",
    canActivate: [AuthGuard],
    component:RtgViewComponent
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

I can create multiple instances of RtgViewComponent & single instance of RtgCreationComponent. I am just opening these components inside a stepper(i,e like browser tabs) by looping & each component instance will be created with dynamic query params for both RtgViewComponent & RtgCreationComponent.

I need to restore form data in RtgCreationComponent after routing from RtgViewComponent & AppComponent.

Issue I am facing is:

If I create RtgCreationComponent first then creates multiple number of RtgViewComponent. Then routing back to
RtgCreationComponent from RtgViewComponent/AppComponent works fine(i,e form data/router instance wont't be destroyed).

but

If I create RtgViewComponent first, then creates RtgCreationComponent.Then routing back to
RtgCreationComponent from RtgViewComponent breaks the router instacne but routing back from AppComponent work fine.

Please suggest what wrong with my router-strategy.ts code

Was able to reproduce in stackblitz, Attaching FYR.

like image 923
Shankar Avatar asked Oct 17 '25 20:10

Shankar


2 Answers

Custom RouteReuseStrategy is a bad idea nearly in 100% cases. It is much more complicated than it may seem, it is error prone and API documentation is also very bad on this topic.

RouteReuseStrategy can only cache component tree, you can not cache individual components.

I don't completely understand your case but I think it is not possible to make strategy better than default one. Just cache data instead of caching component instances.

like image 84
kemsky Avatar answered Oct 19 '25 08:10

kemsky


First:

path: "form/:rtgId/:email/:phnNumber/view",

Should be before

path:"form/:rtgId/:email/:phnNumber",

Second: you should subscribe to ActivateRouter.Params

constructor(private activateRouter:ActivateRouter){}
ngOnInit(){
   this.activateRouter.Params.subscribe(res=>{
       ...
   }
}
like image 21
Eliseo Avatar answered Oct 19 '25 08:10

Eliseo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!