Question

Get URL Query Parameters in Angular 5 with ActivatedRoute

typescriptangularangular-routing

Question

In an Angular 5.0.3 application, how can I read query parameters when the application starts with a URL such as:

/app?param1=hallo&param2=123

I currently read parameters directly from the browser URL:

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

However, I would like to use Angular's routing APIs instead. In the root component below, how can I access the query parameters in ngOnInit?

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit {
  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    // Read query parameters here.
  }
}

Short Answer

You will learn how Angular represents query parameters through ActivatedRoute, when to use a one-time snapshot, and when to subscribe so your component responds to URL changes. You will also see how to create URLs with query parameters through Angular's Router.

Concept

Query parameters are the optional key=value values after ? in a URL:

/app?param1=hallo&param2=123

They are commonly used for data that describes a view without changing its route path: search text, page number, sort order, filters, and tracking values.

In Angular, query parameters belong to the router state. Inject ActivatedRoute into a routed component and read either:

  • route.snapshot.queryParamMap when you only need the value at component creation.
  • route.queryParamMap when the value may change while Angular keeps the same component instance alive.

Unlike a path parameter such as /products/42, query parameters are not tied to one route segment. They are available from the active route, including a root-level AppComponent in a router-based application.

Use Angular's router APIs rather than manually parsing window.location.search. The router understands Angular navigation, works with route changes, and makes components easier to test.

Mental Model

Think of a route as the address of a building:

  • The path is the street address: /products/42.
  • Query parameters are notes attached to the address: ?tab=reviews&sort=newest.

ActivatedRoute is Angular's delivery slip for the current address. A snapshot is a photograph of the slip at one moment. An observable is a notification service that gives you a new slip whenever the query parameters change.

Take Quiz

Syntax and Examples

Inject ActivatedRoute and use queryParamMap.

Read once with a snapshot

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

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit {
  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    const param1 = this.route.snapshot.queryParamMap.get('param1');
    const param2 = this.route.snapshot.queryParamMap.get('param2');

    console.log(param1); // "hallo"
    console.log(param2); // "123"
  }
}

get() returns string | null, because the URL might not contain that parameter. URL values are always strings, so param2 is initially the string "123", not the number 123.

React to later changes

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

@Component({
  selector: 'app-results',
  template: '<p>Search: {{ searchTerm }}</p>'
})
export class ResultsComponent implements OnInit {
  searchTerm = '';

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    this.route.queryParamMap.subscribe(params => {
      this.searchTerm = params.get('q') || '';
    });
  }
}

When the URL changes from /results?q=angular to /results?q=router, the subscription runs again and updates searchTerm.

Older object-style API

Angular 5 also provides queryParams:

this.route.queryParams.subscribe(params => {
  const param1 = params['param1'];
});

queryParamMap is usually clearer because it explicitly provides parameter access through get(), has(), and getAll().

Step by Step Execution

Consider this URL:

/results?q=angular&page=2

And this component:

ngOnInit(): void {
  this.route.queryParamMap.subscribe(params => {
    const query = params.get('q') || '';
    const pageText = params.get('page') || '1';
    const page = Number(pageText);

    console.log(query, page);
  });
}

Execution proceeds as follows:

  1. Angular creates ResultsComponent for the /results route.
  2. Angular injects the current ActivatedRoute into the constructor.
  3. ngOnInit subscribes to queryParamMap.
  4. The router emits the current parameter map.
  5. params.get('q') returns "angular".
  6. params.get('page') returns "2".
  7. Number("2") converts the URL string to the number 2.
  8. The console receives angular 2.

If Angular later navigates to /results?q=typescript&page=3 without destroying the component, the observable emits again and repeats steps 5 through 8 with the new values.

Real World Use Cases

  • Search pages: /search?q=angular supplies the text used to load results.
  • Pagination: /orders?page=3&pageSize=25 determines which records an API request should fetch.
  • Filtering: /products?category=books&inStock=true represents selected filters.
  • Sorting: /products?sort=price&direction=asc preserves the user's ordering choice.
  • Tabs and display state: /account?tab=security opens a particular section.
  • Shareable views: A user can copy a filtered report URL and another user sees the same view.

Do not treat query parameters as trusted input. Validate values before using them in business logic or sending them to an API.

Take Quiz

Real Codebase Usage

Production components typically normalize and validate query parameters before using them.

Use defaults and validate numbers

this.route.queryParamMap.subscribe(params => {
  const requestedPage = Number(params.get('page') || '1');

  this.page = Number.isInteger(requestedPage) && requestedPage > 0
    ? requestedPage
    : 1;
});

This prevents values such as ?page=-2 or ?page=hello from breaking pagination.

Load data when parameters change

this.route.queryParamMap.subscribe(params => {
  const search = params.get('q') || '';
  this.productService.search(search).subscribe(products => {
    this.products = products;
  });
});

For rapidly changing parameters, such as a search field that updates the URL, real projects often use RxJS operators such as map, filter, debounceTime, distinctUntilChanged, and switchMap to avoid unnecessary requests.

Navigate through the Router

Create or update query parameters with Router, not by concatenating strings:

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

constructor(private router: Router) {}

showPage(page: number): void {
  this.router.navigate(['/results'], {
    queryParams: { q: 'angular', page: page }
  });
}

To retain existing parameters while changing one value:

this.router.navigate([], {
  queryParams: { page: 2 },
  queryParamsHandling: 'merge'
});

In a component that is destroyed when navigation occurs, Angular normally cleans up route-observable subscriptions. If you subscribe to longer-lived observables or use a component that can persist, apply the project's standard unsubscribe pattern.

Common Mistakes

Expecting a number instead of a string

This URL parameter is text:

const page = this.route.snapshot.queryParamMap.get('page');
// page is "2", not 2

Convert and validate it:

const page = Number(this.route.snapshot.queryParamMap.get('page') || '1');

Forgetting that a parameter can be missing

Broken code:

const term = this.route.snapshot.queryParamMap.get('q');
console.log(term.toUpperCase());

get('q') can return null. Provide a fallback:

const term = this.route.snapshot.queryParamMap.get('q') || '';
console.log(term.toUpperCase());

Using a snapshot when the URL can change in place

A snapshot does not update after component creation:

const page = this.route.snapshot.queryParamMap.get('page');

Use queryParamMap.subscribe(...) if the same component must react to later query-parameter navigation.

Reading path parameters as query parameters

For /users/42, 42 is generally a path parameter, read with paramMap. For /users?id=42, id is a query parameter, read with queryParamMap.

Manually parsing window.location.search

new URLSearchParams(window.location.search)

This can work in a browser, but it bypasses Angular's router state and does not naturally react to router navigation. Prefer ActivatedRoute in Angular components.

Using the wrong route level

In nested routing, a route-specific path parameter may be on this.route.parent or a child route. Query parameters are shared across the current navigation, but organize route access in the component that owns the relevant view whenever possible.

Comparisons

NeedBest APIWhy
Read query parameters once at initializationroute.snapshot.queryParamMapSimple one-time lookup
React when query parameters changeroute.queryParamMapEmits updated values
Read /products/42route.paramMap42 is part of the path
Read /products?page=2route.queryParamMappage follows ?
Navigate with query parametersrouter.navigate(..., { queryParams })Lets Angular construct the URL
Parse the browser URL manuallyURLSearchParamsUsually unnecessary inside Angular routed components

queryParams and queryParamMap both expose query parameters. queryParams provides a plain object, while queryParamMap provides methods such as get('key') and better communicates that a parameter may have multiple values.

Take Quiz

Cheat Sheet

// Inject the active route
constructor(private route: ActivatedRoute) {}

// Read once
const value = this.route.snapshot.queryParamMap.get('key');

// React to changes
this.route.queryParamMap.subscribe(params => {
  const value = params.get('key');
});

// Check for a value
const exists = this.route.snapshot.queryParamMap.has('key');

// Read repeated values
const tags = this.route.snapshot.queryParamMap.getAll('tag');

// Create a URL with query parameters
this.router.navigate(['/results'], {
  queryParams: { q: 'angular', page: 2 }
});

// Keep existing query parameters while changing one
this.router.navigate([], {
  queryParams: { page: 2 },
  queryParamsHandling: 'merge'
});

Rules:

  • Query parameters begin after ? and are separated by &.
  • get() returns string | null.
  • Convert numeric and boolean-looking values yourself.
  • Use a snapshot for a fixed initial value; use the observable for changes.
  • Use paramMap for path parameters and queryParamMap for query parameters.

FAQ

How do I get query parameters in Angular 5?

Inject ActivatedRoute, then use this.route.snapshot.queryParamMap.get('name') for an initial value or subscribe to this.route.queryParamMap for updates.

Why does get('page') return a string?

All URL query parameter values are text. Convert the value with Number() or another validation function when you need a number.

What happens if the query parameter does not exist?

queryParamMap.get('name') returns null. Use a default, such as params.get('name') || ''.

Should I use queryParams or queryParamMap?

Both work in Angular 5. queryParamMap is often easier to read because it has explicit methods including get, has, and getAll.

Can AppComponent read query parameters?

Yes. Injecting ActivatedRoute into AppComponent can read query parameters. For route-specific screen logic, it is usually cleaner to read them in the routed page component.

How do I preserve query parameters during navigation?

Use queryParamsHandling: 'merge' in router.navigate() when you want to update some values while keeping existing ones.

Do query parameter changes recreate the component?

Not necessarily. Angular may reuse the same component for the same route path. Subscribe to queryParamMap if your component must update when only query parameters change.

Take Quiz

Mini Project

Description

Build a small results page that reads q and page from the URL. The page displays the active search term and page number, and its buttons update the URL through Angular's router. This mirrors the URL-driven state used by search and catalog pages.

Goal

Create a results page that keeps its displayed search state synchronized with ?q=...&page=....

Requirements

Requirement 1

Take Quiz

Keep learning

Related questions

View more