Search code examples
angularangular-routingrouterlinkangular-routerlink

Angular - Issue with routerLink and state


From an html page I want to route to another page using routerLink and state. There's no issues with <a> tag, during ngOnInit in landing page, I can retrieve state as expected. Using <button> tag home page is navigate as well but state results undefined.

What's my wrong?

html of login page

<button routerLink="/home" [state]="navExtra.state">
    Go Home Page via button
</button>
<a routerLink="/home" [state]="navExtra.state">Go Home Page via a</a>

ts of login page

import { Component, OnInit } from '@angular/core';
import { NavigationExtras } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss']
})
export class LoginPage implements OnInit {
  navExtra: NavigationExtras = {
    state: { data: { a: 'a', b: 'b' } }
  };
  constructor() {}

  ngOnInit() {}
}

ts of home page

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-home',
  templateUrl: './home.page.html',
  styleUrls: ['./home.page.scss']
})
export class HomePage implements OnInit {
  constructor(
    private router: Router
  ) {}

  ngOnInit() {
    console.log(this.router.getCurrentNavigation().extras.state);
  }
}

Solution

  • I don't think it is possible to pass state through a button. If we inspect the source code of routerLink, we can see...

    when not an a tag:

    @Directive({selector: ':not(a):not(area)[routerLink]'})
    

    state isn't included in extras:

    @HostListener('click')
    onClick(): boolean {
      const extras = {
        skipLocationChange: attrBoolValue(this.skipLocationChange),
        replaceUrl: attrBoolValue(this.replaceUrl),
      };
      this.router.navigateByUrl(this.urlTree, extras);
      return true;
    }
    

    source

    whereas when we have an a tag:

    @Directive({selector: 'a[routerLink],area[routerLink]'})
    

    it is included:

    @HostListener('click', [/** .... **/])
    onClick(/** .... **/): boolean {
      // .....
      const extras = {
        skipLocationChange: attrBoolValue(this.skipLocationChange),
        replaceUrl: attrBoolValue(this.replaceUrl),
        state: this.state // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< here!
      };
      this.router.navigateByUrl(this.urlTree, extras);
      return false;
    }
    

    source

    So your option is to style that link to look like a button, or then call a function on button click which performs the navigation, like presented in other answer, here I kindly refer to that code posted by AbolfazlR:

    this.router.navigate(['home'], this.navExtra);