angularangular2-routingmulti-tenantangular-routerlink

Router in global navigation always give me / even using relative path


I'm trying to create an app with a global nav (in AppComponent before router-outlet) and subroutes. The web app is built on the multi-tenant model with an url like this http://serveraddress/tenantSpace/:tenantUrl/ and I can't get the result I want in my routerLinks relative paths. I always get a / instead of full param path.

Here is what I tried:

So the route of each tenant will start after /tenantSpace/:tenantUrl/. So what I have for my routerLinks in my navigation is something like:

<a routerLink="./page1">Page1</a>

which I expect will give me:

<a routerLink="/tenantSpace/tenantSpace1/page1" href="/tenantSpace/tenantSpace1/page1">Page1</a>

The problem is that I always get /page1. The relative path is not evaluated even if I'm on a page at the same level as Page1 for example in /tenantSpace/tenantSpace1/page2.

If I put a routerlink inside the page1 component I get the good router.url but when the global navigation in AppComponent is evaluated the router.url is always /

So I'm sure I don't understand the way routing works in Angular and I don't find any ressources on this. If someone could help I would be very grateful.

Here is a stackblitz to illustrate the issue (you will find my route configuration inside):

Sample project


Solution

  • Acutally ./ routing means the relative position of the current route of the component, since its in app.component the relative positioning is / so angular is working fine!

    To solve your problem, you need to create a component called webspaces this will contain <router-outlet/> inside that we will subscribe the latest value of the params webSpaceName and store it in a service. Like so

    webspaces.com.ts

    import { Component } from '@angular/core';
    import { ActivatedRoute, RouterOutlet, Params } from '@angular/router';
    import { WebspaceService } from '../webspace.service';
    import { Subscription } from 'rxjs';
    @Component({
      selector: 'app-webspaces',
      standalone: true,
      imports: [RouterOutlet],
      templateUrl: './webspaces.component.html',
      styleUrl: './webspaces.component.scss',
    })
    export class WebspacesComponent {
      subscription: Subscription = new Subscription();
      constructor(
        private activatedRoute: ActivatedRoute,
        private webspaceService: WebspaceService
      ) {
        this.subscription.add(
          this.activatedRoute.params.subscribe((params: Params) => {
            this.webspaceService.webspace = params?.['webSpaceName'] || '';
          })
        );
      }
    
      ngOnDestroy() {
        this.subscription.unsubscribe();
      }
    }
    

    webspaces html

    <router-outlet/>
    

    In the root component when we route, we append the parameter and then perform the routing as shown below!

    app html

    <nav>
      <a [routerLink]="['webspaces', webspace, 'properties']">Properties</a>
    </nav>
    <router-outlet></router-outlet>
    

    app ts

    import { Component } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { RouterLink, RouterModule, RouterOutlet } from '@angular/router';
    import { WebspaceService } from './webspace.service';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [CommonModule, RouterOutlet, RouterModule, RouterLink],
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss'],
    })
    export class AppComponent {
      title = 'AppTest';
    
      get webspace() {
        return this.webspaceService.webspace;
      }
    
      constructor(private webspaceService: WebspaceService) {}
    }
    

    stackblitz -> cd test -> npm i -> npm run start