Reactive and type-safe query parameter management using Angular Signals.
🔁 Two-way binding between URL query parameters and application state, powered by Angular’s modern reactivity model.
- ✅ Auto-synced signals from query parameters
- ✅ Two-way binding: update signals → update URL
- ✅ Works with primitive types, arrays, booleans, numbers, enums, and more
- ✅ Fully tree-shakable, Angular-native
- ✅ Zero extra dependencies
Using NPM:
npm install @geckosoft/ngx-query-params
Using YARN:
yarn add @geckosoft/ngx-query-params
Ensure your app uses Angular's Signals (Angular v17+).
No special setup needed—just import and use in any Angular component or service.
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { qpNum } from '@geckosoft/ngx-query-params';
@Component({
selector: ...,
imports: [FormsModule],
template: `
<input type="number" [(ngModel)]="page">
<button (click)="nextPage()">Next Page</button>
`,
})
export class MyComponent {
page = qpNum('page', 1); // ?page=1
nextPage() {
this.page.set(this.page() + 1);
}
}
toggle = qpBool('debug', false); // ?debug=true
filter = qp('filter', 'all'); // ?filter=all
sort = qp('sort'); // string | undefined
type Tab = 'home' | 'profile' | 'settings';
tab = qpCast1<Tab>('tab', 'home'); // ?tab=home
tags = qpMapN('tag', (x) => x.toLowerCase()); // ?tag=a&tag=b
- Hooks into Angular Router's
ActivatedRoute
andqueryParamMap
- Syncs with
WritableSignal<T>
- A global
QueryParamsService
batches and updates the URL when any param changes
Function | Type | Description |
---|---|---|
qp() |
WritableSignal<string | undefined> |
String param |
qpNum() |
WritableSignal<number | undefined> |
Number param |
qpBool() |
WritableSignal<boolean | undefined> |
Boolean param |
qpCast1<T>() |
WritableSignal<T | undefined> |
Cast to enum/union type |
qpMapN() |
WritableSignal<T[]> |
Multi-value param with mapping |
qpMap1() |
WritableSignal<T | undefined> |
Generic one-value mapper |
You can inject QueryParamsService
to manually batch or set multiple parameters:
constructor(private readonly qps: QueryParamsService) {}
applyFilters() {
this.qps.set('filter', 'recent');
this.qps.set('limit', 20);
}
No need to manually unsubscribe—internally handles onDestroy()
and signal disposal.
MIT
Issues and PRs welcome!