Understanding Query Parameters in Angular

Query parameters are an essential part of modern web development. They allow developers to pass additional information in the URL without modifying the actual route. This makes them particularly useful for search functionality, filtering data, pagination, or passing state between components. Angular provides a powerful mechanism for handling query parameters using the Router and ActivatedRoute services.

What are Query Parameters?

Query parameters are key-value pairs appended to a URL, usually after a ? symbol. For example, in the URL:

/search?q=angular
  • The path /search corresponds to the route.
  • The query parameter q=angular provides additional information to the component without changing the route itself.

Query parameters differ from route parameters (/user/:id) in that route parameters are mandatory parts of the URL structure, whereas query parameters are optional and can be dynamically added or removed.

Adding Query Parameters in Angular

Angular provides the Router service to navigate between routes programmatically. Query parameters can be added using the queryParams option. Here’s a basic example:

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

@Component({
  selector: 'app-search-button',
  template: <button (click)="searchAngular()">Search Angular</button>
})
export class SearchButtonComponent {
  constructor(private router: Router) {}

  searchAngular() {
this.router.navigate(['/search'], { queryParams: { q: 'angular' } });
} }

Explanation of the Code

  1. Router Service: Injected into the component constructor, the Router allows programmatic navigation.
  2. navigate() Method: Used to navigate to a specific route.
  3. queryParams Object: Contains the key-value pairs to append to the URL. In this example, the URL becomes /search?q=angular.

Accessing Query Parameters

Once query parameters are added to a URL, the target component can access them using the ActivatedRoute service. This service provides a snapshot or an observable of the current route information.

Using snapshot

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

@Component({
  selector: 'app-search',
  template: <p>Search Query: {{ query }}</p>
})
export class SearchComponent implements OnInit {
  query!: string;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
this.query = this.route.snapshot.queryParamMap.get('q')!;
} }

Using Observable queryParams

For dynamic query parameters that may change without reloading the component:

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

@Component({
  selector: 'app-search',
  template: <p>Search Query: {{ query }}</p>
})
export class SearchComponent implements OnInit {
  query!: string;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
this.route.queryParams.subscribe(params => {
  this.query = params['q'];
});
} }

Difference Between Snapshot and Observable

  • Snapshot: Provides a static snapshot of the route at the time the component is initialized. If the query parameter changes later, the snapshot does not update automatically.
  • Observable: Subscribing to queryParams allows the component to react to changes in the query parameters dynamically without reloading the component.

Multiple Query Parameters

Angular supports multiple query parameters in the URL. For example:

this.router.navigate(['/search'], { queryParams: { q: 'angular', page: 2, sort: 'asc' } });

Resulting URL:

/search?q=angular&page=2&sort=asc

In the component:

this.route.queryParams.subscribe(params => {
  const searchQuery = params['q'];
  const page = params['page'];
  const sortOrder = params['sort'];
});

Combining Route Parameters and Query Parameters

It is possible to use route parameters and query parameters together. For example:

const routes: Routes = [
  { path: 'user/:id', component: UserComponent }
];

Navigating programmatically with query parameters:

this.router.navigate(['/user', 42], { queryParams: { ref: 'dashboard' } });

URL generated:

/user/42?ref=dashboard

Accessing in the component:

this.route.paramMap.subscribe(params => {
  const userId = params.get('id');
});

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

Preserving Query Parameters During Navigation

Sometimes, when navigating to another route, we may want to preserve existing query parameters. Angular provides the queryParamsHandling option:

this.router.navigate(['/search'], { queryParamsHandling: 'preserve' });
  • preserve: Keeps existing query parameters.
  • merge: Merges new query parameters with existing ones.

Example:

this.router.navigate(['/search'], { queryParams: { sort: 'desc' }, queryParamsHandling: 'merge' });

If the current URL is /search?q=angular, the resulting URL will be:

/search?q=angular&sort=desc

Using Query Parameters in Links

Angular allows binding query parameters directly in templates using routerLink:

<a [routerLink]="['/search']" [queryParams]="{ q: 'angular', page: 1 }">Search Angular</a>

Advantages

  • Declarative syntax
  • Easy to maintain in HTML templates
  • Works seamlessly with Angular routing

Practical Example: Search and Filter

Imagine a search component with multiple filters:

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

@Component({
  selector: 'app-filter-search',
  template: `
&lt;input &#91;(ngModel)]="searchQuery" placeholder="Search"&gt;
&lt;select &#91;(ngModel)]="category"&gt;
  &lt;option value="all"&gt;All&lt;/option&gt;
  &lt;option value="books"&gt;Books&lt;/option&gt;
  &lt;option value="electronics"&gt;Electronics&lt;/option&gt;
&lt;/select&gt;
&lt;button (click)="applyFilters()"&gt;Search&lt;/button&gt;
` }) export class FilterSearchComponent { searchQuery: string = ''; category: string = 'all'; constructor(private router: Router) {} applyFilters() {
this.router.navigate(&#91;'/search'], { queryParams: { q: this.searchQuery, cat: this.category } });
} }

In the SearchComponent:

this.route.queryParams.subscribe(params => {
  const query = params['q'];
  const category = params['cat'];
  // Apply filtering logic here
});

Resulting URL example:

/search?q=angular&cat=books

Handling Optional Query Parameters

Query parameters are inherently optional. If a parameter is missing, Angular will return null when accessed via snapshot or undefined via subscription:

const query = this.route.snapshot.queryParamMap.get('q'); // returns null if not present

This allows flexible component behavior depending on which query parameters are provided.

Query Parameters for Pagination

A common use case for query parameters is pagination. For example:

this.router.navigate(['/products'], { queryParams: { page: 3, size: 20 } });

In the component:

this.route.queryParams.subscribe(params => {
  const page = +params['page'] || 1; // default to page 1
  const size = +params['size'] || 10; // default size 10
  this.loadProducts(page, size);
});

This ensures that the current page and page size are reflected in the URL and can be bookmarked or shared.

Query Parameters for Sorting

Similarly, sorting can be managed via query parameters:

this.router.navigate(['/products'], { queryParams: { sort: 'price', order: 'asc' } });

In the component:

this.route.queryParams.subscribe(params => {
  const sortField = params['sort'] || 'name';
  const sortOrder = params['order'] || 'asc';
  this.sortProducts(sortField, sortOrder);
});

This approach allows multiple users to share the same sorting preferences via URL.

Query Parameters and Browser Refresh

Query parameters are part of the URL, so they persist even after the page is refreshed. This makes them ideal for scenarios where application state needs to survive page reloads.

Example:

  • URL before refresh: /search?q=angular&page=2
  • After refresh: Angular automatically parses the query parameters, and the component reads them from ActivatedRoute.

Advantages of Using Query Parameters

  1. State Preservation: Query parameters allow preserving user state across routes.
  2. Dynamic Filtering: Useful for filtering, searching, and sorting data without modifying routes.
  3. Optional Parameters: Unlike route parameters, query parameters are optional and can be added or removed dynamically.
  4. Shareable URLs: Users can copy and share URLs that include query parameters for the same view.
  5. SEO Friendly: Query parameters are visible in the URL and can improve search engine indexing for dynamic content.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *