routerLink to absolute root of the website ("/") while preserving all the named outlets of current URL

108 views Asked by At

In an Angular HTML template, I'm trying to generate a link to the welcome page (root) of my website through the following anchor tag:

<a [routerLink]="['/', { outlets: namedOutlets }]" [relativeTo]="null">

The [relativeTo]="null" is here to specify I don't want to generate a link relative to the current URL, but I rather want an absolute path to "/" (i.e. root of my website). The problem is, as soon as I specify '/' in [routerLink] it's not working anymore (e.g. I get the URL /my/current/path/ instead of /), while when I put something else (like 'foobar') it's working correctly (I do get URL /foobar and not /my/current/path/foobar). It's also working correctly if I remove the outlets and only put [routerLink]="['/']", but of course I do need those outlets.

I also tried things like: [routerLink]="['', { outlets: namedOutlets }]" [relativeTo]="null" or [routerLink]="['.', { outlets: namedOutlets }]" [relativeTo]="null" but it's also not working (e.g. I always get the URL /my/current/path/ instead of /)

FYI, the namedOutlets array is populated in my component with the following code:

export class MyComponent implements OnInit {

namedOutlets: string[] = [];

constructor(private router: Router) {}

ngOnInit(): void {
  const urlTree = this.router.parseUrl(this.router.url);
  if (urlTree.fragment) {
    // Extract named outlets from URL fragments:
    const fragments = urlTree.fragment.split('/');
    fragments.forEach(fragment => {
      if (fragment.includes(':')) {
        const outletName = fragment.split(':')[0];
        if (!this.namedOutlets.includes(outletName)) {
          this.namedOutlets.push(outletName);
        }
      }
    });
  }
}

⇒ is there any way of forcing Angular to operate rationally and logically, in a consistent way, and to respect what it is asked to do?

Thanks in advance for your help

2

There are 2 answers

0
Pigeo On

I finally found the solution:

<a [routerLink]="['/', { outlets: spreadOperator({primary: null}, namedOutlets) }]">

Caveat:

  /**
   * The spread operator (`...`) can not be used from within an Angular template,
   * hence we need to call this wrap function
   * 
   * @param obj1 an object to be merged (with another object)
   * @param obj2 another object to be merged with it
   * @returns an object which is the merge of the 2 objects received in parameters
   */
  public spreadOperator(obj1, obj2): any {
    return { ...obj1, ...obj2};
  }

This solution was inspired to me by another stack overflow question: routerLink absolute url

0
Pigeo On

If you don't need to play with the list of named outlets, the solution is indeed very simple:

<a [routerLink]="['/', { outlets: {primary: null} }]">

No extra Typescript code is necessary.

(by not specifying any named outlets, Angular is going to preserve all of the named outlets found in the current URL)