Search code examples
javascriptangulartypescriptmulti-tenant

Accessing route parameters in Angular 7/8 layout components and services?


I have a multitenant application that identifies tenants based on a route parameters called organization. I have various portions of the application that need to change behavior based upon the organization passed in through the route parameter, but I'm running into some issues accessing the parameter anywhere other than the component that the router has navigated to.

In multiple areas of my application, I've placed a variant of the following code:

export class OrganizationSidebarComponent implements OnInit {

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.route.params.subscribe(params => {
      console.log('[OrganizationSidebarComponent] ID IS ' + params['organization']);
      console.log(params);
    });
    this.route.paramMap.subscribe(paramMap => {
      console.log('[OrganizationSidebarComponent] ID from ParamMap: ' + paramMap.get('organization'));
    });
    console.log('[OrganizationSidebarComponent] ID using snapshot paramMap: ' + this.route.snapshot.paramMap.get('organization'));
    console.log('[OrganizationSidebarComponent] ID using snapshot params: ' + this.route.snapshot.params.organization);
  }
}

However, when the pages are navigated to, the output looks like the following: Console output

My routes are setup like so:

const routes: Routes = [
  {
    path: 'Organization',
    component: OrganizationsLayoutComponent,
    children: [
      {
        path: ':organization',
        component: OrganizationDashboardComponent,
        canActivate: [AuthGuard]
      }
    ]
  }
];

In a perfect world, I'd be able to access the values from some injected service so that I have a centralized fetching service that I can leverage to obtain the required information, but I'm simply having issues retrieving the route parameters from anywhere that isn't the component that is being navigated to.

How can I access this information?


Solution

  • I would suggest to do it in another way, (based on your problem statement) instead of reading the organization in many components and loading data, read that in the app.component as below

    add this method in App.component.ts

      mergeRouteParams(router: Router): { [key: string]: string } {
        let params = {};
        let route = router.routerState.snapshot.root;
        do {
          params = { ...params, ...route.params };
          route = route.firstChild;
        } while (route);
    
        return params;
      }
    

    then in ngOnInit do this

        this.router.events.subscribe((e) => {
          if (e instanceof NavigationEnd) {
            const mergedParams = this.mergeRouteParams(this.router);
            console.log(mergedParams);
          }
        });
    

    and of course add private router: Router to your constructor

    Working stackblitz

    https://stackblitz.com/edit/angular-merge-route-params

    Url to check https://angular-merge-route-params.stackblitz.io/dictionary/dict/code

    enter image description here

    Solution 2

    Another way to get all params is using route configuration

    export const routingConfiguration: ExtraOptions = {
        paramsInheritanceStrategy: 'always',
    };
    
    @NgModule({
        imports: [RouterModule.forRoot(routes, routingConfiguration)],
        exports: [RouterModule],
    })
    export class AppRoutingModule { }
    

    now if you inject route: ActivatedRoute in the params or paramsMap you will all params from parents including this child route