316

I'm using angular 5.0.3, I would like to start my application with a bunch of query parameters like /app?param1=hallo&param2=123. Every tip given in How to get query params from url in Angular 2? does not work for me.

Any ideas how to get query parameters work?

private getQueryParameter(key: string): string {
  const parameters = new URLSearchParams(window.location.search);
  return parameters.get(key);
}

This private function helps me to get my parameters, but I don't think it is the right way in new Angular environment.

[update:] My main app looks like

@Component({...})
export class AppComponent implements OnInit {

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    // would like to get query parameters here...
    // this.route...
  }
}
Milo
  • 3,365
  • 9
  • 30
  • 44
Lars
  • 3,576
  • 2
  • 15
  • 13
  • Are you using routers? Where is the URL coming from? – Vinod Bhavnani Nov 23 '17 at 12:37
  • Yes, have a ActivatedRoute. I updated my question to show how my main component looks like. – Lars Nov 23 '17 at 12:53
  • Can you also show me your route constant, where you have setup all the routes? – Vinod Bhavnani Nov 23 '17 at 12:55
  • const appRoutes: Routes = [ {path: "one", component: PageOneComponent}, {path: "", redirectTo: "/one", pathMatch: "full"}, {path: "**", redirectTo: "/one"} ]; My Route constant. I would like to get all parameters in the main app store it in a DTO, then navigate to an other page. Page navigation works as expected, but I get the query parameters at main only by my 'getQueryParameter' function. I realize in your question that there exist something I have forgotten. Do I need to mark my parameter names anywhere? – Lars Nov 23 '17 at 13:19
  • Yes, in your routes, you need to define the parameters as well. If you check the routing docs on angular.io, you can see how they define parameters on a particular route. Something like this {path: 'abc/:param1', component: componentClassName} – Vinod Bhavnani Nov 23 '17 at 13:26
  • Once you have done that, anything in the url after your domain/abc, will be param1. For example, localhost:4200/abc/100, in this case 100 will be param1, which you can access as Dmitri has answered below – Vinod Bhavnani Nov 23 '17 at 13:28
  • Also note that the ActivatedRoute Params object returns an observable, so you need to subscribe to access the param value. – Vinod Bhavnani Nov 23 '17 at 13:30
  • I have round about 10 parameters in different order. Therefore I must use named query parameters. And how do I set my main AppComponent to realize that there are 10 parameters. All samples I read and saw use the simple 'abc/:param1' example. I need a '/?a="value"&b="other value"... where the named parameter 'a' will by value, parameter 'b' will be 'other value' and so on. – Lars Nov 23 '17 at 14:19
  • This article should solve your problem. https://angular-2-training-book.rangle.io/handout/routing/query_params.html – Vinod Bhavnani Nov 23 '17 at 14:30

20 Answers20

366

In Angular 5, the query params are accessed by subscribing to this.route.queryParams (note that later Angular versions recommend queryParamMap, see also other answers).

Example: /app?param1=hallo&param2=123

param1: string;
param2: string;
constructor(private route: ActivatedRoute) {
    console.log('Called Constructor');
    this.route.queryParams.subscribe(params => {
        this.param1 = params['param1'];
        this.param2 = params['param2'];
    });
}

whereas, the path variables are accessed by this.route.snapshot.params

Example: /param1/:param1/param2/:param2

param1: string;
param2: string;
constructor(private route: ActivatedRoute) {
    this.param1 = this.route.snapshot.params.param1;
    this.param2 = this.route.snapshot.params.param2;
}
Jeroen
  • 60,696
  • 40
  • 206
  • 339
Vijayendra Mudigal
  • 4,245
  • 1
  • 14
  • 12
  • 24
    According to Angular 6 [docs](https://angular.io/guide/router#activated-route), the usage of ActivatedRoute.queryParams and .params is discouraged and may be deprecated in future versions; see update [here](https://stackoverflow.com/a/51808539/2313004) – grreeenn Aug 12 '18 at 11:51
  • 1
    @ShubhenduVaid explain why, they should be using the ngOnInit instead of the constructor. Best practice will be using RxJS observable, then use declarative approach when working with observables, then using async on the html – Patricio Vargas Oct 02 '19 at 06:18
  • Following you example 1. this.param1 in any method is coming back as null or undefined. Is there a way to make those values global to be accessed in the whole class. – JayC Aug 20 '20 at 20:44
210

This is the cleanest solution for me

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

export class MyComponent {
  constructor(
    private route: ActivatedRoute
  ) {}

  ngOnInit() {
    const firstParam: string = this.route.snapshot.queryParamMap.get('firstParamKey');
    const secondParam: string = this.route.snapshot.queryParamMap.get('secondParamKey');
  }
}
dapperdan1985
  • 3,132
  • 2
  • 15
  • 26
  • This is helpful, thanks. As of angular 6.0.8, I am using this and it works for me: this.route.snapshot.queryParams["firstParamKey"] – fluidguid Oct 25 '19 at 03:04
  • 3
    This works for me in Angular8. this.route.snapshot.queryParamMap works. this.route.snapshot.paramMap doesn't work for me. – Romeo Profijt Feb 18 '20 at 14:23
  • 6
    @RomeoProfijt ```paramMap``` is for parameters in the route, not query params. If you have a route defined as ```/myroute/:id``` and navigate to ```/myroute/45``` then you can get 45 from ```paramMap.get('id')```. – Stack Underflow Jan 29 '21 at 21:22
126

I know that OP asked for Angular 5 solution, but yet for all of you who stumbles upon this question for newer (6+) Angular versions. Citing the Docs, regarding ActivatedRoute.queryParams (which most of other answers are based on):

Two older properties are still available. They are less capable than their replacements, discouraged, and may be deprecated in a future Angular version.

params — An Observable that contains the required and optional parameters specific to the route. Use paramMap instead.

queryParams — An Observable that contains the query parameters available to all routes. Use queryParamMap instead.

According to the Docs, the simple way to get the query params would look like this:

constructor(private route: ActivatedRoute) { }

ngOnInit() {
    this.param1 = this.route.snapshot.paramMap.get('param1');
    this.param2 = this.route.snapshot.paramMap.get('param2');
}

For more advanced ways (e.g. advanced component re-usage) see this Docs chapter.

EDIT:

As it correctly stated in comments below, this answer is wrong - at least for the case specified by OP.

OP asks to get global query parameters (/app?param1=hallo&param2=123); in this case you should use queryParamMap (just like in @dapperdan1985 answer).

paramMap, on the other hand, is used on parameters specific to the route (e.g. /app/:param1/:param2, resulting in /app/hallo/123).

Thanks to @JasonRoyle and @daka for pointing it out.

Anthony L
  • 2,159
  • 13
  • 25
grreeenn
  • 2,287
  • 1
  • 20
  • 27
40

You can also Use HttpParams, such as:

  getParamValueQueryString( paramName ) {
    const url = window.location.href;
    let paramValue;
    if (url.includes('?')) {
      const httpParams = new HttpParams({ fromString: url.split('?')[1] });
      paramValue = httpParams.get(paramName);
    }
    return paramValue;
  }
a5tr0
  • 543
  • 4
  • 6
  • 1
    Just clarify, I have two domains point to different language site. localhost/ --> En, localhost/?lang=fr --> French. And I have routing: `path: '', redirectTo: '/list' `. The this.route.snapshot doesn't work for me because it redirectTo /list which eliminate the 'lang' queryString. But this solution works for me. – Ryan Huang Sep 28 '18 at 20:22
  • As @RyanHuang I have kind of the same issue. But this solution worked on my first trial. – Gi1ber7 Jun 11 '19 at 17:48
  • Find better solution than above : https://jsonworld.com/blog/retrieve-parameters-and-query-string-values-from-url-in-angular8 – Soni Kumari Sep 04 '19 at 01:41
  • while writing unit tests httpParams.get(paramName) not able to get value. Do you have any Idea how we can we do this? – Khaan Oct 15 '21 at 11:45
  • this is a life saver since changes done to url with `location.replaceState` or `location.go` don't get reflected in `activatedRoute` ... – bersling Jul 01 '22 at 09:49
26

Query and Path Params (Angular 8)

For url like https://myapp.com/user/666/read?age=23 use

import { combineLatest } from 'rxjs';
// ...

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => {
    let userId = pathParams.get('userId');    // =666
    let age    = queryParams.get('age');      // =23
    // ...
  })

UPDATE

In case when you use this.router.navigate([someUrl]); and your query parameters are embedded in someUrl string then angular encodes a URL and you get something like this https://myapp.com/user/666/read%3Fage%323 - and above solution will give wrong result (queryParams will be empty, and path params can be glued to last path param if it is on the path end). In this case change the way of navigation to this

this.router.navigateByUrl(someUrl);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
19
import { ParamMap, Router, ActivatedRoute } from '@angular/router';

constructor(private route: ActivatedRoute) {}

ngOnInit() {
    console.log(this.route.snapshot.queryParamMap);
}

UPDATE

import { Router, RouterStateSnapshot } from '@angular/router';

export class LoginComponent {
    constructor(private router: Router) {
        const snapshot: RouterStateSnapshot = router.routerState.snapshot;
        console.log(snapshot);  // <-- hope it helps
    }
}
Dmitry Grinko
  • 13,806
  • 14
  • 62
  • 86
  • 6
    that seems to be not enough, I get the ActivatedRouteSnapshot but queryParams is an empty object, params also empty and .queryParamMap.get('name') returns null. It seems that ngOnInit() it too early to get such query parameters. – Lars Nov 23 '17 at 13:28
  • actually if you want to get this params you should change your route. – Dmitry Grinko Nov 23 '17 at 13:40
  • I have round about 10 parameters in different order. Therefore I must use named query parameters. And how do I set my main AppComponent to realize that there are 10 parameters. https://url/myprogram?a=1&b=2&c=4... it seams I have a problem? Do I need to route every parameter to an other component? I hope not. – Lars Nov 23 '17 at 14:14
  • Did you try this one? this.route.snapshot.queryParamMap – Dmitry Grinko Nov 23 '17 at 14:22
  • Why do use this params? It is not a good idea to use url to send data. You can use service for example for sharing data. – Dmitry Grinko Nov 23 '17 at 14:30
  • Yes I tried `this.route.snapshot.queryParamMap` but it is empty. I need such parameters as optional parameters. A service it much too complicated for the caller|user here. – Lars Nov 23 '17 at 15:04
  • I use the parameter to fill in some formular input with values. – Lars Nov 23 '17 at 15:36
  • 1
    @DmitryGrinko putting an entity Id into a route is not a bad pattern, It allows for a deep link to a detail view. – Karl Apr 11 '18 at 21:21
  • @Karl Yes, perhaps it makes sense if you need to use deep links but we didn't talk about it. – Dmitry Grinko Apr 11 '18 at 21:25
12

Angular Router provides method parseUrl(url: string) that parses url into UrlTree. One of the properties of UrlTree are queryParams. So you can do sth like:

this.router.parseUrl(this.router.url).queryParams[key] || '';
Adam Michalak
  • 155
  • 1
  • 8
  • 1
    Please don't post multiple identical answers to different questions. There's some useful advice about this practice [here](https://meta.stackexchange.com/questions/104227/is-it-acceptable-to-add-a-duplicate-answer-to-several-questions/211726#211726) – David Buck May 23 '20 at 18:34
  • 2
    Use this if you don't need to deal with URL changes, i.e. the parameters are already available in the current URL. Do it the observable way otherwise. – tom May 25 '20 at 02:20
11

its work for me:

constructor(private route: ActivatedRoute) {}

ngOnInit()
{
    this.route.queryParams.subscribe(map => map);
    this.route.snapshot.queryParams; 
}

look more options How get query params from url in angular2?

izik f
  • 2,387
  • 2
  • 16
  • 17
10

Unfortunately, the cleanest solution is not the most extensible solution. In recent versions of Angular, it is suggested in the other answers that you can easily get the query params using the ActivatedRoute Injectible and specifically utilizing either the snapshot property:

this.route.snapshot.queryParamMap.get('param')

or the subscribe property (used in cases where the query string will update, e.g. navigating through user ids):

this.route.queryParamMap.subscribe(params => console.log(params));

I am here to tell you that these solutions have a gaping flaw that has not been resolved for some time: https://github.com/angular/angular/issues/12157

All in all, the only bullet proof solution is to use good old vanilla javascript. In this case, I created a service for URL manipulation:

import { Injectable } from '@angular/core';
import { IUrl } from './iurl';

@Injectable()
export class UrlService {
    static parseQuery(url: string): IUrl {
        const query = url.slice(url.indexOf('?')+1).split('&').reduce( (acc,query) => {
            const parts = query.split('=');
            acc[parts[0]] = parts[1];
            return acc;
        }, {});

        return {
            a: query['a'],
            b: query['b'],
            c: query['c'],
            d: query['d'],
            e: query['e']
        }
    }
}
Daniel Viglione
  • 8,014
  • 9
  • 67
  • 101
7

Stumbled across this question when I was looking for a similar solution but I didn't need anything like full application level routing or more imported modules.

The following code works great for my use and requires no additional modules or imports.

  GetParam(name){
    const results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if(!results){
      return 0;
    }
    return results[1] || 0;
  }

  PrintParams() {
    console.log('param1 = ' + this.GetParam('param1'));
    console.log('param2 = ' + this.GetParam('param2'));
  }

http://localhost:4200/?param1=hello&param2=123 outputs:

param1 = hello
param2 = 123
Reed
  • 1,515
  • 1
  • 21
  • 38
2

Found in: Parent components gets empty Params from ActivatedRoute

Worked for me:

import {Component, OnDestroy, OnInit} from '@angular/core';
import { Router, ActivatedRoute, Params, RoutesRecognized } from '@angular/router';

@Component({
  selector: 'app-navigation-bar',
  templateUrl: './navigation-bar.component.html',
  styleUrls: ['./navigation-bar.component.scss']
})
export class NavigationBarComponent implements OnInit, OnDestroy {
  private sub: any;
  constructor(private route: ActivatedRoute, private router: Router) {}

  ngOnInit() {
    this.sub = this.router.events.subscribe(val => {
      if (val instanceof RoutesRecognized) {
        console.log(val.state.root.firstChild.params);
      }
    });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }

}
Yonatan Ayalon
  • 1,959
  • 18
  • 19
2

Simple Solution

 // in routing file
       {
            path: 'checkout/:cartId/:addressId',
            loadChildren: () => import('./pages/checkout/checkout.module').then(m => m.CheckoutPageModule)
          },

    // in Component file

            import { Router, ActivatedRoute } from '@angular/router';

                 constructor(
                      private _Router: ActivatedRoute
                  ) { }

                  ngOnInit() {
                    this.cartId = this._Router.snapshot.params.cartId;
                    this.addressId = this._Router.snapshot.params.addressId;
                    console.log(this.addressId, "addressId")
                    console.log(this.cartId, "cartId")
                  }
Shashwat Gupta
  • 5,071
  • 41
  • 33
2

The best solution is to use ActivatedRoute:

    constructor(private route: ActivatedRoute) {}
    
    ngOnInit(): void {
        this.route.queryParams.subscribe((params) => {
         console.log(params);
         const queryparams = params['queryName'];
        });
    }
Nick Vu
  • 14,512
  • 4
  • 21
  • 31
Abhinav Akhil
  • 173
  • 1
  • 7
1

When you have an empty route object, it's mainly due to the fact that you are not using a router-outlet in your app.component.html.

Without this, you won't be able to get a meaningful route object with non empty subObjects, particularly params & queryParams.

Try to add <router-outlet><router-outlet>just before calling your <app-main-component></app-main-component>

Before that, make sure you have your query param ready in app-routing > which export the class Route used by App component :

param: '/param/:dynamicParam', path: MyMainComponent

Last thing of course, to get your param, I personnaly use this.route.snapshot.params.dynamicParam where dynamicParam is the name used in your app-routing component :)

andrea06590
  • 1,259
  • 3
  • 10
  • 22
1

Be careful with your routes. A "redirectTo" will remove|drop any query parameter.

const appRoutes: Routes [
 {path: "one", component: PageOneComponent},
 {path: "two", component: PageTwoComponent},
 {path: "", redirectTo: "/one", pathMatch: full},
 {path: "**", redirectTo: "/two"}
]

I called my main component with query parameters like "/main?param1=a&param2=b and assume that my query parameters arrive in the "ngOnInit()" method in the main component before the redirect forwarding takes effect.

But this is wrong. The redirect will came before, drop the query parameters away and call the ngOnInit() method in the main component without query parameters.

I changed the third line of my routes to

{path: "", component: PageOneComponent},

and now my query parameters are accessible in the main components ngOnInit and also in the PageOneComponent.

Lars
  • 3,576
  • 2
  • 15
  • 13
1

This worked for me. I have used child routes in the routing module.


 this.route.firstChild.snapshot.paramMap.get('id');
   
Susan
  • 11
  • 3
0

Just stumbled upon the same problem and most answers here seem to only solve it for Angular internal routing, and then some of them for route parameters which is not the same as request parameters.

I am guessing that I have a similar use case to the original question by Lars.

For me the use case is e.g. referral tracking:

Angular running on mycoolpage.com, with hash routing, so mycoolpage.com redirects to mycoolpage.com/#/. For referral, however, a link such as mycoolpage.com?referrer=foo should also be usable. Unfortunately, Angular immediately strips the request parameters, going directly to mycoolpage.com/#/.

Any kind of 'trick' with using an empty component + AuthGuard and getting queryParams or queryParamMap did, unfortunately, not work for me. They were always empty.

My hacky solution ended up being to handle this in a small script in index.html which gets the full URL, with request parameters. I then get the request param value via string manipulation and set it on window object. A separate service then handles getting the id from the window object.

index.html script

const paramIndex = window.location.href.indexOf('referrer=');
if (!window.myRef && paramIndex > 0) {
  let param = window.location.href.substring(paramIndex);
  param = param.split('&')[0];
  param = param.substr(param.indexOf('=')+1);
  window.myRef = param;
}

Service

declare var window: any;

@Injectable()
export class ReferrerService {

  getReferrerId() {
    if (window.myRef) {
      return window.myRef;
    }
    return null;
  }
}
seBaka28
  • 932
  • 1
  • 7
  • 16
-1
/*
Example below url with two param (type and name) 
URL : http://localhost:4200/updatePolicy?type=Medicare%20Insurance&name=FutrueInsurance
*/ 
  constructor(private route: ActivatedRoute) {
    //Read url query parameter `enter code here`
  this.route.queryParams.subscribe(params => {
    this.name= params['type'];
    this.type= params['name'];
    alert(this.type);
    alert(this.name);

 });

  }
-3

At, i think Angular 8:

ActivatedRoute.params has been replaced by ActivatedRoute.paramMap ActivatedRoute.queryParams has been replaced by ActivatedRoute.queryParamMap

marvinfrede
  • 1,055
  • 5
  • 12
  • 2
    This is not true: see https://v8.angular.io/api/router/ActivatedRoute for Angular 8 and here for current Angular 10: https://angular.io/guide/router#activated-route. ActivatedRoute has all four properties. – Stefan Sep 01 '20 at 06:05
-12

If you're not using Angular router try, querystring. Install it

npm install --save querystring

to your project. In your component do something like this

import * as qs from 'querystring';
...
ngOnInit() {
   const params = qs.parse(window.location.search.substring(1));
   ...
}

The substring(1) is necessary because if you have something like this '/mypage?foo=bar' then the key name for will be ?foo

Chuk Lee
  • 3,570
  • 22
  • 19