32

I have router link like below:

<button class="take-a-tour-btn" [routerLink]="['/dashboard', {'showTour':'show'}]">

I want to pass parameter showTour. But, when I do this, the parameter is visible in url and I would like to hide it. I have gone through so many references(which says about optional parameters) ,but with no success in my case. How could I solve this?

Vega
  • 27,856
  • 27
  • 95
  • 103
Sai M.
  • 2,548
  • 4
  • 29
  • 46

7 Answers7

39

You can use History state to pass dynamic data to the component you want to navigate to, without adding them into the URL, like so :

this.router.navigateByUrl('/user', { state: { orderId: 1234 } });

or

<a [routerLink]="/user" [state]="{ orderId: 1234 }">Go to user's detail</a>

and you can get it this way

constructor() {
  this.router.events
   .pipe(filter(e => e instanceof NavigationStart))
   .subscribe((e: NavigationStart) => {
    const navigation  = this.router.getCurrentNavigation();
    this.orderId = navigation.extras.state ? navigation.extras.state.orderId : 0;
   });
 }
Fateh Mohamed
  • 20,445
  • 5
  • 43
  • 52
17

I'm not sure, if there is a way to do it, because the data need to be presented in the URL string.

My suggestion is using global service which be store needed data. For example:

//some dataService, which store your needed data.
@Injectable()
export class DataService {

   _showTour: string;

   set showTour(value: string) {
      this._showTour = value;
   }

   get showTour(): string {
       return this._showTour;
   }

   constructor() {}

}

and use it in your navigation component in this way:

//your navigation component
@Component({
    selector: 'my-app',
    template: `
       <button class="take-a-tour-btn" (click)="onClick()">
    `
})
export class SomeComponent {
    constructor(private dataService: DataService, private router: Router) { }

    onClick() {
        this.dataService.showTour = 'show';
        this.router.navigate(['/dashboard']);
    }
}

You will may use the same service in your Dashboard Component, and get needed value, f.e. in this way:

//your dashboard component
@Component({
    selector: 'my-dashboard',
    template: `
       <h1>{{ showTour }}</h1>
    `
})
export class DashboardComponent implements OnInit {

    showTour: string;

    constructor(private dataService: DataService) { }

    ngOnInit() {
        this.showTour = this.dataService.showTour;
    }
}
Jaroslaw K.
  • 5,224
  • 2
  • 39
  • 65
  • Thank you @Jaroslaw K.. I pass the parameters only from one location. So, I don't need that service anywhere else. Using a separate service for that small data is not good I think. – Sai M. Oct 24 '17 at 09:01
  • @SaiUnique Never get hung up on the 'size' of a service in Angular. In fact don't even think of them as 'services' - think of them as 'shared objects'. – Simon_Weaver Aug 06 '18 at 22:30
  • 1
    You can also hack away with something like `this.router['navigationData'] = data` and `let data = this.router['navigationData']` on the other side. The router is initialized only once and it's still a dictionary-like javascript object anyways, so I'm using this for now and I really hope that this remains possible in the next angular versions. The bad part is that you need to be responsible, because this way stores data not only between navigations, but on a global ng service, thus, it would be wise to clean up on the receiving side. – Felype Jan 22 '19 at 11:14
  • @Felype This seemed like a good choice, but unfortunately, this didn't work on Angular 7. – Xonshiz Jun 16 '20 at 13:20
  • It won't work if you're moving from one module to the next and the provider for router is different, in my application I have only 1 provider for router and it's on the root app module, that thing that I said I do is a gimmick because I know the router is a javascript object that angular loads and keeps in memory, you could use any service for that purpose though. – Felype Jun 17 '20 at 12:14
9

Use state to pass hidden parameters and history to read 'em.

First component:

this.router.navigate(
      [`/dashboard/roles/${id}`],
      { state: { navSettings: navSettings } });

Second component:

public ngOnInit(): void {
    const id = this.activatedRoute.snapshot.params.id;
    this.initNavSettings(history.state.navSettings);
}
Buzzy
  • 1,783
  • 18
  • 15
  • This is best solution, it just needs a bit more of comments. `state` is in facts [Javascript history state](https://developer.mozilla.org/en-US/docs/Web/API/History/state) so there is no need to use `Router`/`ActivatedRoute` to access it, just use plain Javascript `history.state`. – luca.vercelli Jul 25 '23 at 09:18
4
<button class="take-a-tour-btn" [routerLink]="['/dashboard', {'showTour':'show', skipLocationChange: true}]">

Try using skipLocationChange property.

AddWeb Solution Pvt Ltd
  • 21,025
  • 5
  • 26
  • 57
  • 2
    Thank you @AddWeb Solution Pvt Ltd. The `parameters` still appear in `url` with your solution. My `url` changes when that link is clicked. But, parameters which I pass should not appear in `url`. – Sai M. Oct 24 '17 at 09:16
2

Try this in your component:(I am using it with Angular 5.x)

this.router.navigate(['/dashboard'], {skipLocationChange: true, replaceUrl: false});
hbthanki
  • 549
  • 1
  • 7
  • 11
0

@AddWeb @SailiUnique

Your solution works but you don't have to put the property in the [routLink]. The correct place is outside it as any property.

Like this:

<div class="row inline rowItem" [routerLink]="['/businessPartnerDetails']" [queryParams]="{ id: bpItem.id, bp: bpItem.companyName}" skipLocationChange=true (click)="onViewDetails(bpItem)">

0

The response isn't exactly efficient because the skipLocationChange don't change the current route on browser url and if you want to go back later, you backed from the first route.

For example if you were on home page and use this:

<button class="take-a-tour-btn" [routerLink]="['/dashboard', {'showTour':'show', skipLocationChange: true}]">Go to dashboard</button>

if you want to back from dashboard to home you can't do that with object location, in this case, you need to use Router and specify an exactly route (/dashboard).

But this in much cases this is a bad solution, and the browser routing don't change from /home to dashboard.

Inconvenients:

  • The browser don't refresh to the correct url
  • You can't go back from dashboard (current route)

You can create the data service or check the official angular router docs

duprez
  • 1
  • 1