How to get query params from url in Angular 2?

TypescriptAngular

Typescript Problem Overview


I use angular2.0.0-beta.7. When a component is loaded on a path like /path?query=value1 it is redirected to /path. Why were the GET params removed? How can I preserve the parameters?

I have an error in the routers. If I have a main route like

@RouteConfig([
  {
      path: '/todos/...',
      name: 'TodoMain',
      component: TodoMainComponent
  }
])

and my child route like

@RouteConfig([
  { path: '/', component: TodoListComponent, name: 'TodoList', useAsDefault:true },
  { path: '/:id', component: TodoDetailComponent, name:'TodoDetail' }
])

then I can't get params in TodoListComponent. I am able to get

params("/my/path;param1=value1;param2=value2") 

but I want the classic

query params("/my/path?param1=value1&param2=value2")

Typescript Solutions


Solution 1 - Typescript

By injecting an instance of ActivatedRoute one can subscribe to a variety of observables, including a queryParams and a params observable:

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

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

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        const userId = params['userId'];
        console.log(userId);
      });
  }

}

A NOTE REGARDING UNSUBSCRIBING

@Reto and @codef0rmer had quite rightly pointed out that, as per the official docs, an unsubscribe() inside the components onDestroy() method is unnecessary in this instance. This has been removed from my code sample. (see blue alert box in this tutorial)

Solution 2 - Typescript

When a URL is like this http://stackoverflow.com?param1=value

You can get the param 1 by the following code:

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

@Component({
	selector: '',
	templateUrl: './abc.html',
	styleUrls: ['./abc.less']
})
export class AbcComponent implements OnInit {
	constructor(private route: ActivatedRoute) { }

	ngOnInit() {
		// get param
		let param1 = this.route.snapshot.queryParams["param1"];
	}
}

Solution 3 - Typescript

Even though the question specifies version beta 7, this question also comes up as top search result on Google for common phrases like angular 2 query parameters. For that reason here's an answer for the newest router (currently in alpha.7).

The way the params are read has changed dramatically. First you need to inject dependency called Router in your constructor parameters like:

constructor(private router: Router) { }

and after that we can subscribe for the query parameters on our ngOnInit method (constructor is okay too, but ngOnInit should be used for testability) like

this.router
  .routerState
  .queryParams
  .subscribe(params => {
    this.selectedId = +params['id'];
  });

In this example we read the query param id from URL like example.com?id=41.

There are still few things to notice:

  1. Accessing property of params like params['id'] always returns a string, and this can be converted to number by prefixing it with +.
  2. The reason why the query params are fetched with observable is that it allows re-using the same component instance instead of loading a new one. Each time query param is changed, it will cause a new event that we have subscribed for and thus we can react on changes accordingly.

Solution 4 - Typescript

I really liked @StevePaul's answer but we can do the same without extraneous subscribe/unsubscribe call.

import { ActivatedRoute } from '@angular/router';
constructor(private activatedRoute: ActivatedRoute) {
    let params: any = this.activatedRoute.snapshot.params;
    console.log(params.id);
    // or shortcut Type Casting
    // (<any> this.activatedRoute.snapshot.params).id
}

Solution 5 - Typescript

To send query params
import { Router } from '@angular/router';
this.router.navigate([ '/your-route' ], { queryParams: { key: va1, keyN: valN } });
To receive query params
import { ActivatedRoute } from '@angular/router';
this.activatedRoute.queryParams.subscribe(params => {
    let value_1 = params['key'];
    let value_N = params['keyN'];
});

Official source

Solution 6 - Typescript

Hi you can use URLSearchParams, you can read more about it here.

import:

import {URLSearchParams} from "@angular/http";

and function:

getParam(){
  let params = new URLSearchParams(window.location.search);
  let someParam = params.get('someParam');
  return someParam;
}

Notice: It's not supported by all platforms and seems to be in "EXPERIMENTAL" state by angular docs

Solution 7 - Typescript

Get URL param as an object.

import { Router } from '@angular/router';
constructor(private router: Router) {
	console.log(router.parseUrl(router.url));
}

Solution 8 - Typescript

First off, what I have found working with Angular2 is that the url with a query string would be /path;query=value1

To access it in a component you use So is this, but now follows a code block:

    constructor(params: RouteParams){
    var val = params.get("query");
    }

As to why it would be removed when you load the component, that isn't default behavior. I checked specificly in a clean test project and wasn't redirected or changed. Is it a default route or something else that is special about the routing?

Read about routing with query strings and params in the Angular2 Tutorial at https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters

Solution 9 - Typescript

You can get the query parameters when passed in URL using ActivatedRoute as stated below:-

url:- http:/domain.com?test=abc

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

@Component({
  selector: 'my-home'
})
export class HomeComponent {

  constructor(private sharedServices : SharedService,private route: ActivatedRoute) { 
    route.queryParams.subscribe(
      data => console.log('queryParams', data['test']));
  }

}

Solution 10 - Typescript

now it is:

this.activatedRoute.queryParams.subscribe((params: Params) => {
  console.log(params);
});

Solution 11 - Typescript

If you only want to get query parameter once, the best way is to use take method so you do not need to worry about unsubscription. Here is the simple snippet:-

constructor(private route: ActivatedRoute) {
  route.snapshot.queryParamMap.take(1).subscribe(params => {
     let category = params.get('category')
     console.log(category);
  })
}

Note: Remove take(1) if you want to use parameter values in future.

Solution 12 - Typescript

I hope it will help someone else.

Question above states that query param value is needed after page has been redirected and we can assume that snapshot value (the no-observable alternative) would be sufficient.

No one here mentioned about snapshot.paramMap.get from the https://angular.io/guide/router#snapshot-the-no-observable-alternative">official documentation.

this.route.snapshot.paramMap.get('id')

So before sending it add this in sending/re-directing component:

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

then re-direct as either (documented https://angular.io/guide/router#heroes-list-optionally-selecting-a-hero">here</a>;):

this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);

or simply:

this.router.navigate(['/heroes', heroId ]);

Make sure you have added this in your routing module as documented https://angular.io/guide/router#hero-feature-routing-requirements">here</a>;:

 { path: 'hero/:id', component: HeroDetailComponent }

And finally, in your component which needs to use the query param

( documentation also imports switchMap and also injects Router and HeroService - but they are needed for observable alternative only - they are NOT needed when you use snapshot alternative as in our case ):

    constructor(
      private route: ActivatedRoute
    ) {}

NOTE: IF YOU ADD ROUTING-MODULE TO A FEATURE MODULE (AS SHOWN IN DOCUMENTATION) MAKE SURE THAT IN APP.MODULE.ts THAT ROUTING MODULE COMES BEFORE AppRoutingModule (or other file with root-level app routes) IN IMPORTS: [] . OTHERWISE FEATURE ROUTES WILL NOT BE FOUND (AS THEY WOULD COME AFTER { path: '**', redirectTo: '/not-found' } and you would see only not-found message).

Solution 13 - Typescript

You just need to inject ActivatedRoute in constructor and then just access params or queryParams over it

constructor(private route:ActivatedRoute){}
ngOnInit(){
        this.route.queryParams.subscribe(params=>{
        let username=params['username'];
      });
 }

In Some cases it doesn't give anything in NgOnInit ...maybe because of init call before initialization of params in this case you can achieve this by asking observable to wait for some time by function debounceTime(1000)

e.g=>

 constructor(private route:ActivatedRoute){}
    ngOnInit(){
            this.route.queryParams.debounceTime(100).subscribe(params=>{
            let username=params['username'];
          });
     }

debounceTime() Emits a value from source observable only after particular time span passed without another source emission

Solution 14 - Typescript

Query and Path (Angular 8)

If you have url like https://myapp.com/owner/123/show?height=23 then use

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => {
    let ownerId = pathParams.get('ownerId');    // =123
    let height  = queryParams.get('height');    // =height
    // ...
  })

UPDATE

In case when you use this.router.navigate([yourUrl]); and your query parameters are embedded in yourUrl string then angular encodes a URL and you get something like this https://myapp.com/owner/123/show%3Fheight%323 - and above solution will give wrong result (queryParams will be empty, and query 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(yourUrl);

Solution 15 - Typescript

My old school solution:

queryParams(): Map<String, String> {
  var pairs = location.search.replace("?", "").split("&")
  var params = new Map<String, String>()
  pairs.map(x => {
    var pair = x.split("=")
    if (pair.length == 2) {
      params.set(pair[0], pair[1])
    }
  })

  return params
}

Solution 16 - Typescript

You cannot get a parameter from the RouterState if it's not defined in the route, so in your example, you have to parse the querystring...

Here is the code I used:

let re = /[?&]([^=#&]+)=([^&#]*)/g;
let match;
let isMatch = true;
let matches = [];
while (isMatch) {
    match = re.exec(window.location.href);
    if (match !== null) {
        matches[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
        if (match.index === re.lastIndex) {
            re.lastIndex++;
        }
    }
    else {
        isMatch = false;
    }
}
console.log(matches);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFireGMView Question on Stackoverflow
Solution 1 - TypescriptStephen PaulView Answer on Stackoverflow
Solution 2 - TypescriptTrungView Answer on Stackoverflow
Solution 3 - TypescriptRoope HakulinenView Answer on Stackoverflow
Solution 4 - Typescriptcodef0rmerView Answer on Stackoverflow
Solution 5 - TypescriptdddenisView Answer on Stackoverflow
Solution 6 - TypescriptAsaf HananelView Answer on Stackoverflow
Solution 7 - TypescriptJsonrasView Answer on Stackoverflow
Solution 8 - TypescriptNamirnaView Answer on Stackoverflow
Solution 9 - TypescriptSaurabhView Answer on Stackoverflow
Solution 10 - TypescriptAlanView Answer on Stackoverflow
Solution 11 - TypescriptAbhishek ChandelView Answer on Stackoverflow
Solution 12 - TypescriptUlaView Answer on Stackoverflow
Solution 13 - TypescriptRajivView Answer on Stackoverflow
Solution 14 - TypescriptKamil KiełczewskiView Answer on Stackoverflow
Solution 15 - TypescriptAlexandrView Answer on Stackoverflow
Solution 16 - TypescriptJulien RicardView Answer on Stackoverflow