66

In my app some URLs take the form

/department/:dep/employee/:emp/contacts

In my sidebar I show a list of all employees, each of which has a [routerLink] which links to that employee's contacts

<ul>
    <li>
        <a [routerLink]="['/department', 1, 'employee', 1, 'contacts']"></a>
    <li>
    <li>
        <a [routerLink]="['/department', 1, 'employee', 2, 'contacts']"></a>
    <li>
    ...
</ul>

However, with this approach I always need to provide the full path, including all the params (like dep in the above example) which is quite cumbersome. Is there a way to provide just part of the route, such as

<a [routerLink]="['employee', 2, 'contacts']"></a>

(without the department part, because I don't really care about department in that view and my feeling is that this goes against separation of concerns anyway)?

Thorsten Westheider
  • 10,572
  • 14
  • 55
  • 97

4 Answers4

87

That's supposed to work. The leading / makes it an absolute route, without it (or with ./), it becomes a relative route relative to the current route. You can also use ../ (or ../../ or more) to route relative to the parent or parents parent.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 2
    Neither with `./` nor without it do relative `routerLink`s work. They work once after page load, but if the parent component changes its part of the URL the `href` generated for the component with the relative `routerLink` is not updated and stays on the previous route. See my repo at https://github.com/erasethis/angular2-routing – Thorsten Westheider Jul 07 '16 at 04:42
  • I guess that needs Plunker to reproduce and investigate https://angular.io/resources/live-examples/quickstart/ts/plnkr.html Do you have a `` as first element inside ``? – Günter Zöchbauer Jul 07 '16 at 04:45
  • 6
    I think it's relative to the route of the component in which `routerLink` is defined. If I've actived a `/parent/child/grandchild1` route and `routerLink` is defined in the `/parent` component (which contains the sidebar for OP), then a link to `grandchild2` would still expect `routerLink` to include `child`, eg. `[routerLink]="[child, grandchild2]"`. – adamdport May 25 '17 at 17:47
  • 3
    Can confirm. `./` does work and loads child component wrt current route. – PsyGik Dec 05 '17 at 05:40
  • @pbarranis "it simply isn't working"—without more details I can't help you. If your issue is different than OPs, try to reproduce in a stackblitz and post your own question – adamdport Sep 19 '18 at 14:40
  • Old question/answer, but I don't see anything mentioned in here about the base url which the router would need. – Jacques Oct 26 '18 at 14:33
  • @Jacques I don't see why that would be related – Günter Zöchbauer Oct 26 '18 at 18:42
  • @GünterZöchbauer doesn't the router base relative paths off the base URL? – Jacques Oct 30 '18 at 06:55
  • @Jacques relative routes are based on the current route, similar to the current working directory. `../sibling`, `../../uncle/cousin`, `child`. Absolute routes are based on base URL. – Günter Zöchbauer Oct 30 '18 at 07:03
16

Instead of using './' or '../', I would suggest using relativeTo param in router.navigate function. E.g.:

this.router.navigate(['child'], {relativeTo: this.route});

or

this.router.navigate(['sibling'], {relativeTo: this.route.parent});
Terry Lam
  • 1,025
  • 1
  • 12
  • 13
14

In case your app-routing.module.ts looks similar to this:

  {
    path: '/department/:dep', component: DepartmentComponent, children: [
      { path: 'employee/:emp/contacts', component: EmployeeComponent },
      // ... Other child routes
    ]
  }

Assuming you are on the parent route http://localhost:4200/department/1, now the below routerLinks will work as mentioned:

  1. Prefix ./ represents relative path from current route
  2. No Prefix represents relative path from current route
  3. Prefix / represents absolute path from root route
  4. Prefix ../ represents relative path to move up one level from current route
<ul>

  <!-- will generate URL: http://localhost:4200/department/1/employee/1/contacts-->
  <li class="nav-item">
     <a class="nav-link" routerLink="recipes" routerLink="./employee/1/contacts">Relative Link that Works!:)</a>
  </li>

  <!-- is same as above and generated URL: http://localhost:4200/department/1/employee/1/contacts-->
  <li class="nav-item">
     <a class="nav-link" routerLink="recipes" routerLink="employee/1/contacts">Relative Link that Works!:)</a>
  </li>

  <!-- is same as above and generated URL: http://localhost:4200/department/1/employee/1/contacts-->
  <li class="nav-item">
     <a class="nav-link" routerLink="recipes" [routerLink]="['employee', '1', 'contacts']">Relative Link that Works! :)</a>
  </li>

  <!-- is NOT THE SAME as above  and generated URL: http://localhost:4200/department/employee/1/contacts-->
  <li class="nav-item">
     <a class="nav-link" routerLink="recipes" routerLink="../employee/1/contacts">Relative Link that does NOT work! :( </a>
  </li>

  <!-- is NOT THE SAME as above  and generated URL: http://localhost:4200/employee/1/contacts-->
  <li class="nav-item">
     <a class="nav-link" routerLink="recipes" routerLink="/employee/1/contacts">Absolute Link that does NOT work! :( </a>
  </li>

</ul>
RICHARD ABRAHAM
  • 2,218
  • 20
  • 26
11

As described also in the official Angular doc here View

<ul>
    <li>
        <a (click)="onViewDetails(id)">Details</a>
    <li>
    ...

Component

construct( private router: Router, private route: ActivatedRoute ){
}
onViewDetails(id){
 this.router.navigate([id], {relativeTo: this.route});
}

/employee
/employee/:id

ErvTheDev
  • 4,390
  • 3
  • 16
  • 20
  • @adamdport which version of Angular are you refering? Angular has changed a lot since my answer :D you can check the official docs for more info on the router..thnx – ErvTheDev May 26 '17 at 09:00
  • @user776686 Angular being a SPA it does not have a "way" of "open in a new tab" but you can achieve it easily with window object of JS. Check this code: ``` let newRelativeUrl = router.createUrlTree([id], {relativeTo: this.route}); let baseUrl = window.location.href.replace(router.url, ''); window.open(baseUrl + newRelativeUrl, '_blank'); ``` I did not test it but should work in theory. – ErvTheDev Oct 27 '21 at 09:11