Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular merge parent route data with current route

Tags:

angular

rxjs

I would like to have an easy way to access all the route data of the parents at the current child route, this seems like it would be a common task am I missing something built into angular?

Example

const routes: Routes = [
  {
    path: '',
    component: WrapperComponent,
    data: {
      prop1: 'abc',
    },
    children: [
      {
        path: '',
        component: HomeComponent,
        data: {
          prop2: '1',
          prop3: 'Some other data',
        },
      },
      {
        path: 'welcome',
        data: {
          prop1: 'efg',
          prop2: 'my cool prop',
        },
      },
];

My goal would be some sort of property of the activated route that returns the merged route data so if at:

/ - the route data would be

{
   prop1: 'abc',
   prop2: '1',
   prop3: 'Some other data',
}

/welcome - the route data would be

{
   prop1: 'efg',
   prop2: 'my cool prop',
}

I have implemented this with the following code but I bet someone better with observables could write this better.

this.router.events  // private router: Router,
  .pipe(
    filter((event) => event instanceof NavigationEnd),
    map(() => this.activatedRoute),
    map((route) => {
      let data: any = {};
      while (route.firstChild) {
        data = { ...data, ...route.firstChild.snapshot.data };
        route = route.firstChild;
      }
      return data;
    }),
  ).subscribe((e) => console.log(e));

Does this functionality already exist in angular?

like image 427
JoAMoS Avatar asked Oct 14 '25 18:10

JoAMoS


2 Answers

I think it's possible to do that by using paramsInheritanceStrategy: 'always' when you set RouterModule:

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { paramsInheritanceStrategy: 'always' })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }
like image 96
Brozorec Avatar answered Oct 17 '25 09:10

Brozorec


I believe this should work:

constructor(router: Router) {
  router.events.pipe(
    filter(e => e instanceof ActivationEnd),
    buffer(router.events.pipe(filter(e => e instanceof NavigationEnd), debounceTime(0))),
    map((events: ActivationEnd[]) => events.reduce((acc, curr) => ({ ...acc, ...curr.snapshot.data }), {}))
  );
}
  1. Filter out for the ActivationEnd events (we have the route snapshots there so we can get the data for the individual routes from them)

  2. buffer them until we've gotten all the NavigationEnd events for the current stack

  3. reduce over all the buffered events and collect the data inside one object (collisions are not handled)

like image 29
user1 Avatar answered Oct 17 '25 10:10

user1