Reading Query Parameters in Angular

Query parameters are a key part of web application URLs, allowing developers to pass additional information between views without changing the main route. In Angular, accessing query parameters in a component is straightforward and extremely useful for building dynamic applications, such as search functionality, filtering lists, and displaying content conditionally.

This article explores how to read query parameters in Angular, with detailed examples, best practices, and advanced usage.

Introduction to Query Parameters

A URL often contains query parameters to pass information:

https://example.com/products?q=laptop&category=electronics
  • q=laptop is a query parameter for a search term.
  • category=electronics is another query parameter specifying a product category.

Query parameters differ from route parameters:

  • Route parameters are part of the URL path (e.g., /user/1).
  • Query parameters are optional and follow the ? symbol.

Angular provides the ActivatedRoute service to access query parameters easily.


Setting Up Angular for Query Parameters

To demonstrate query parameter handling, let’s create a simple Angular application with a search functionality.

  1. Create a new Angular project:
ng new angular-query-demo
cd angular-query-demo
  1. Generate components:
ng generate component search
ng generate component results
  1. Configure routes:

Open app-routing.module.ts:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { SearchComponent } from './search/search.component';
import { ResultsComponent } from './results/results.component';

const routes: Routes = [
  { path: '', component: SearchComponent },
  { path: 'results', component: ResultsComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Using Query Parameters in Angular

Angular uses the ActivatedRoute service to provide access to query parameters.

Basic Example

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

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

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
this.route.queryParamMap.subscribe(params => {
  this.query = params.get('q');
  console.log(this.query);
});
} }
  • queryParamMap is an observable that contains all query parameters.
  • params.get('q') retrieves the value of the query parameter named q.
  • Using .subscribe() ensures the component reacts to changes in query parameters dynamically.

Passing Query Parameters via routerLink

To use query parameters, you can pass them in the template using [queryParams] with routerLink.

<a [routerLink]="['/results']" [queryParams]="{ q: 'laptop' }">Search Laptop</a>
<a [routerLink]="['/results']" [queryParams]="{ q: 'phone' }">Search Phone</a>

Clicking these links navigates to /results?q=laptop or /results?q=phone without reloading the page.


Query Parameters in Forms

Search functionality often comes from a form input. Angular allows binding form values to query parameters.

Example: Search Form

<form (submit)="search(searchInput.value)">
  <input #searchInput type="text" placeholder="Enter search term">
  <button type="submit">Search</button>
</form>
import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html'
})
export class SearchComponent {
  constructor(private router: Router) {}

  search(query: string) {
this.router.navigate(&#91;'/results'], { queryParams: { q: query } });
} }
  • The Router.navigate() method accepts a queryParams object.
  • Users can type a search term, and the query parameter updates dynamically.

Multiple Query Parameters

Query parameters can include multiple values.

this.router.navigate(['/results'], { 
  queryParams: { q: 'laptop', category: 'electronics', sort: 'price' } 
});

In the component:

ngOnInit(): void {
  this.route.queryParamMap.subscribe(params => {
const query = params.get('q');
const category = params.get('category');
const sort = params.get('sort');
console.log(query, category, sort);
}); }

This allows creating rich and dynamic filters in applications.


Handling Changes in Query Parameters

Query parameters can change without navigating to a new route. For example, users might change a filter dynamically.

Angular’s queryParamMap observable ensures components react to changes in real-time.

ngOnInit(): void {
  this.route.queryParamMap.subscribe(params => {
this.query = params.get('q');
this.category = params.get('category');
this.applyFilters();
}); } applyFilters() { console.log('Filters applied:', this.query, this.category); }

Using queryParamsHandling for Navigation

When navigating programmatically, you might want to preserve existing query parameters.

this.router.navigate(['/results'], { 
  queryParams: { page: 2 }, 
  queryParamsHandling: 'merge' 
});
  • 'merge' preserves existing parameters and adds new ones.
  • 'preserve' keeps all current query parameters without changes.

Reading Query Parameters with snapshot

If you only need the query parameters once, you can use ActivatedRoute.snapshot.queryParamMap.

ngOnInit(): void {
  const query = this.route.snapshot.queryParamMap.get('q');
  console.log('Snapshot query:', query);
}
  • snapshot is not reactive.
  • It’s faster for one-time reads but won’t update if parameters change.

Query Parameters with Angular Forms

You can bind Angular Reactive Forms or Template-driven Forms to query parameters for enhanced search experiences.

Reactive Form Example

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

@Component({
  selector: 'app-search',
  template: `
&lt;input &#91;formControl]="searchControl" placeholder="Search"&gt;
` }) export class SearchComponent implements OnInit { searchControl = new FormControl(''); constructor(private router: Router, private route: ActivatedRoute) {} ngOnInit(): void {
this.route.queryParamMap.subscribe(params =&gt; {
  this.searchControl.setValue(params.get('q'));
});
this.searchControl.valueChanges.subscribe(value =&gt; {
  this.router.navigate(&#91;], { queryParams: { q: value }, queryParamsHandling: 'merge' });
});
} }
  • This keeps the input field synchronized with query parameters.
  • Changes in the input update the URL dynamically without page reload.

Best Practices for Query Parameters

  1. Use Observables for Dynamic Data: Subscribe to queryParamMap for real-time updates.
  2. Preserve Query Parameters When Necessary: Use queryParamsHandling: 'merge'.
  3. Use Meaningful Parameter Names: Avoid cryptic names like ?a=1.
  4. Combine with Route Guards: Validate query parameters when necessary.
  5. Avoid Overusing Query Parameters: Use them for filtering and dynamic content, not for essential navigation paths.

Real-World Use Cases

  1. Search Pages:
/products?q=laptop
  • Users can filter and search products dynamically.
  1. Pagination:
/products?page=2&size=10
  • Controls page number and size of results dynamically.
  1. Sorting and Filtering:
/products?category=electronics&sort=price
  • Filter and sort content without reloading the page.
  1. Dynamic Forms:
  • Populate forms based on query parameters for better user experience.

Complete Example

<!-- search.component.html -->
<form (submit)="search(searchInput.value)">
  <input #searchInput type="text" placeholder="Search term">
  <button type="submit">Search</button>
</form>
// search.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html'
})
export class SearchComponent {
  constructor(private router: Router) {}

  search(query: string) {
this.router.navigate(&#91;'/results'], { queryParams: { q: query } });
} }
// results.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-results',
  template: &lt;p&gt;Search query: {{ query }}&lt;/p&gt;
})
export class ResultsComponent implements OnInit {
  query: string | null = '';

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
this.route.queryParamMap.subscribe(params =&gt; {
  this.query = params.get('q');
  console.log(this.query);
});
} }

This example demonstrates a fully functional query parameter-based search system in Angular.


Comments

Leave a Reply

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