Write Angular like a pro. Angular Icon

Follow the ultimate Angular roadmap.

Access parent Route params with Angulars Router

With the router/URL being an application’s “source of truth”, we need to be able to access parts of the URL for data purposes, such as grabbing a dynamic :id property from the URL, passing it into a service and bringing back the relevant data. Let’s look at how we can use Angular’s Observable-driven Router so get automatic updates when a parent route changes.

Scenario

I’m currently working on building out Ultimate Angular’s platform, and as such have these routes (in the URL, not my routing definitions) - with us assuming 1234 is our dynamic :id:

/admin/courses/1234/metadata
/admin/courses/1234/curriculum
/admin/courses/1234/prices
/admin/courses/1234/coupons

What this structure allows me to do is click a particular “course” from /admin/courses, and be navigated to the /1234/metadata view where I can edit the course’s name, author and so forth.

Parent Route Param subscriptions

What I needed to do is (based on the parent’s param), is go off to my Store and fetch the appropriate course I’m viewing.

First let’s walk through the routes:

// routes
export const ROUTES: Routes = [
  {
    path: '',
    canActivate: [CoursesGuard],
    component: CoursesComponent,
  },
  {
    path: ':id',
    canActivate: [CoursesGuard],
    component: CourseComponent,
    children: [
      { path: '', redirectTo: 'metadata', pathMatch: 'full' },
      { path: 'metadata', component: CourseMetadataComponent },
      { path: 'curriculum', component: CourseCurriculumComponent },
      { path: 'prices', component: CoursePricesComponent },
      { path: 'coupons', component: CourseCouponsComponent },
    ],
  },
];

When my path is '', I use the CoursesComponent, and when we navigate to (for example /courses/1234/) - the CourseComponent is loaded (non-plural version). At this point, this CourseComponent is simply a container which renders a ``. Once we hit that :id, we’re directed to the first child route, metadata.

Angular Directives In-Depth eBook Cover

Free eBook

Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.

  • Green Tick Icon Observables and Async Pipe
  • Green Tick Icon Identity Checking and Performance
  • Green Tick Icon Web Components <ng-template> syntax
  • Green Tick Icon <ng-container> and Observable Composition
  • Green Tick Icon Advanced Rendering Patterns
  • Green Tick Icon Setters and Getters for Styles and Class Bindings

Let’s look what’s inside the CourseMetadataComponent, paying attention to ActivatedRoute and the course$ Observable:

// ... other imports etc.
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'course-metadata',
  styleUrls: ['course-metadata.component.scss'],
  template: `
    <div class="course-metadata">
     {{ course$ | async | json }}
    </div>
  `,
})
export class CourseMetadataComponent {
  course$ = this.router.parent.params.switchMap(params =&gt; {
    return this.store
      .select(getCoursesState)
      .map((courses: any) =&gt; courses.courses.find(course =&gt; course._id === params.id));
  });

  constructor(
    private router: ActivatedRoute,
    private store: Store
  ) {}

}

At this point, the switchMap is given the params Object, which as you can see is driven from this.router.parent.params - which you may have used this before (without the .parent):

// not the parent, it's the current param
course$ = this.router.params.switchMap(params => {
  // do something with local "params"
});

So what is params when we do this?

course$ = this.router.parent.params.switchMap(params => {
  // params = { id: 1234 }
});

In my case, with /admin/courses/1234/metadata, the params on the parent are in fact an Object containing { id: 1234 }.

This means from */1234/metadata, */1234/curriculum, */1234/prices and */1234/coupons - I have access to 1234 for passing off into ngrx/store to fetch the correct course. The courses are always available when hitting these routes because I’m using:

{
  canActivate: [CoursesGuard];
}

This way, it’ll make an API request if ngrx/store doesn’t contain any courses, otherwise it’ll pass the API request and head straight across to the correct course, pulling the data from the pre-populated store.

Learn Angular the right way.

The most complete guide to learning Angular ever built.
Trusted by 82,951 students.

Todd Motto

with Todd Motto

Google Developer Expert icon Google Developer Expert

Related blogs 🚀

Free eBooks:

Angular Directives In-Depth eBook Cover

JavaScript Array Methods eBook Cover

NestJS Build a RESTful CRUD API eBook Cover