angular: RouterLink: incorrect relative link if defined in component having empty path

I’m submitting a … (check one with “x”)

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior In the case of such router config with ContainerComponent consuming empty path:

const routes = [
  { 
    path: '', 
    component: ContainerComponent,
    children: [
      { path: 'a', component: AComponent },
      { path: 'b', component: BComponent },
    ]
  }
];

and ContainerComponent having relative links to children in template:

<a [routerLink]="['a']">Link to A</a>     (or  <a [routerLink]="['./a']">Link to A</a>)
<a [routerLink]="['b']">Link to B</a>

RouterLink directive generates incorrect links when user navigated to one of the child component. F.e. if user went to /a route, links would be like that: /a/(a) and /a/(b).

Expected behavior

Relative links should be generated properly: /a and /b.

Minimal reproduction of the problem with instructions http://plnkr.co/edit/Lf2Vfe?p=preview Click on any link. Then you could see that links rendered in AppComponent are correct, but not the ones in ContainerComponent (they both look like /a/(a) and /a/(b)).

What is the motivation / use case for changing the behavior?

Please tell us about your environment:

  • Angular version: 2.2.1
  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
  • Language: [all | TypeScript X.X | ES6/7 | ES5]

  • Node (for AoT issues): 4.2.1

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 63
  • Comments: 50 (12 by maintainers)

Commits related to this issue

Most upvoted comments

i think you maybe missed something.read docs,you will get it .

Hello, I have the same problem. If there is a route localhost/parent/child and I have a [routerLink]="[../sibling]" link, it creates the url localhost/parent/child/sibling instead of localhost/parent/sibling.

The only way to get the desired behavior is to use absolute links, which is undesirable with standalone modules.

The problem occurs only if I use a module with links to sub-modules. For example an authorization module with a login module, sing up module etc. I can not link from the sign up module to the login module without using absolute links. If I change the routing to only use the components (LoginComponent, RegisterComponent) and all these are accessible from the authorization module, the relative links work.

sounds like a legit bug

I have the same problem. It looks like the router doesn’t resolve urls which either don’t have a path, or are abstract paths (no component).

export const ROUTES = [
  {
    // Index route job or product admin selection
    path: '',
    component: ProductsRoute
  },
  {
    path: ':locale',
    resolve: { categories: CategoriesResolver },
    children: [
      {
        // Index route for categories
        path: '',
        component: CategoriesRoute
      },
      {
        path: ':categoryId',
        resolve: { category: CategoryResolver },
        children: [
          {
            // Index route for a category
            path: '',
            component: CategoryRoute
          },
          {
            path: ':productId',
            component: ProductRoute,
            resolve: { product: ProductResolver }
          },
        ]
      },
    ]
  }
];

When I’m in a category and try to link up one level with

<a routerLink="../">Parent</a>

I’m still getting /en/1 instead of /en

I’ve iven tried doing it from the Category Component with the same result

const urlTree = this.router.createUrlTree(['../'], { relativeTo: this.route });
console.log('CategoryRoute URL: ', urlTree.toString()); // outputs /en/1

on Angular7 and still not working

Imho the routerlink relative path should not look at the actual url tree you create to build your routes, as you regurarly add empty paths to add resolves etc… So it should not depend on that, the relative routerlink should depend on the actual url created from the tree.

We now have broken links everytime we add a level for resolves that depend on each other…

So I think it works as designed, but it’s designed badly…

Just reporting my understanding of this issue: It’s not a bug but actually how the router is designed to work with relative routes. The routing is done based on the the router config ‘tree’ which does not necessarily match what the URL path is. Once I understood this - and that lazy loading adds another notch in the tree that needs traversing with relative router - I could work with it fine.

However I do feel that it would be nice to also have relative routing based on URL path NOT router tree. I’ve written some little helpers to do this when I need to and I think when most people think of relative routing they are expecting it to work like this.

My work around for routing one level up from the current URL is something like this:

const url = this.router.url.split('?')[0];
const split = url.split('/');
split.pop();
const newUrl = split.length > 1 ? split.join('/') : '/';
this.router.navigateByUrl(newUrl);

Q: Would you like to see easy relative routing based on URL path as well as route config tree?

@pauldraper That’s because angular router works on ActivatedRoute and not by the URL. This means if you have the follow:

[
 {
  path: 'hello'
  component: HelloComponent,
  children: [
   {
     path: ''
     component: ContainerComponent,
     children: [
      {
        path: 'world'
        component: WorldComponent
      }
     ]
   }
  ]
]

Your URL for the world component will look like this: domain.tld/hello/world however, the Active router will look more like this.

Hello => Container => World

This means when you are using relative path and you need to get back to Hello you will need to go back twice: “…/…/” first takes you to the container and the next will actually take you to the hello.

@DzmitryShylovich Yeah, absolute paths work just fine. Problem comes when used relative path. It’s necessary to use relative path for example in case of reusable module with own navigation bar and which is connected to components tree on quite deep level. It’s not very handy to provide variable with path from the root.

Bug still hppanes in Angular 8.1.2. Also tried to add relativeLinkResolution. Did not work.

This also occurs in Angular 8.1.3, I added relativeLinkResolution to ExtraConfig, but it didn’t fix the issue.

March 23rd 2019 - Angular 7 This issue has still not been resolved.

Hi all,

#22394 has been approved by the core team! Hopefully it’ll be released with v6.1!

I’m an suffering to no end with relative route issues too… I think there might also be something in play when using lazy loading that also affects it too see: #17957

I’ve ran into unbelievable issues just trying to relative route from /parent/:someid/child to /parent/:someid

Absolute routes are a pain in this scenario when you have params in the url and would have to rebuild the absolute route with the current param… very frustrating.

@pgiemza I’ll try what you’re suggesting too and report back

Still seeing this error with Angular 4.2.4. Using absolute links is pretty annoying indeed.

It seems to me that I did everything right according to docs. Maybe I missed something. But… @DzmitryShylovich Did you manage to see that links look like /a/(a) and /a/(b)

Enough ../ works. Specifically, you need to add as many extra as you have current paths.

So if the current URL is /my/url/for/my/angular/app and you want to go to /my/url, you need 6 + 4

routerLink="../../../../../../../../../.."

Coming a novice, I know if that if I write <a href="../../../.."> works just fine. IDK why Angular router would be so much different.

This is still an issue

Solved for me. Add prefix ‘/’ for your path in routeLink. It works for me. I think without this prefix angular can not realize that this is a segment of route. It must be like this: <a [routerLink]=“/a”>Link to A
<a [routerLink]=“/b”>Link to B

Using relativeLinkResolution = ‘corrected’ fixed the problem for me. It must be defined in your routes that are defined with forRoot.

Example: https://angular.io/guide/router#configuration

@niggoo It has been fixed already. You need to use relativeLinkResolution: 'corrected' in your router configuration.

See #22394 for more details.

I had the same issue and found (as @juliusstoerrle found) that I need to include a bunch of additional …/ in my relative link, so I want to navigate from /admin/code/organization/users/allusers to /admin/code/organization/user, but these are in nested modules which are lazy loaded so in my case to get this to work I need [routerLink]="['../../../../../../user']" which need 4 additional …/

Would be great to get any update on a fix for this issue as I know my application will break when this is eventually resolved

Same problem here…

The issue also appears to exists with optional parameters