# wrQueryParam

> A writable signal linked to one query parameter: follows the address, writes it on set, one navigation per task, the default left out.

Source: https://ngwr.dev/reference/utils/wr-query-param  
Kind: Util  
Added in v15.5  
Optional

## Installation

Import the class, and `@use` the entry point in your global styles. Nothing warns you when the `@use` is missing.

```typescript
import { Component } from '@angular/core';
import { WrButton } from 'ngwr/button';
import { WrInput } from 'ngwr/input';
import { WrPagination } from 'ngwr/pagination';
import { wrQueryParam } from 'ngwr/utils/router';

@Component({ imports: [WrButton, WrInput, WrPagination] })
export class MyComponent {}
```

```scss
@use 'ngwr/button';
@use 'ngwr/input';
@use 'ngwr/pagination';
```

## Usage

`set` and `update` work as on any signal. The signal takes the value at once, and one navigation per task carries every write made in it. Needs an injection context. Lives in `ngwr/utils/router`, since `@angular/router` is an optional peer.

```angular-ts
import { wrQueryParam } from 'ngwr/utils/router';

@Component({
  template: `
    <input wrInput type="search" [value]="q()" (input)="q.set($any($event.target).value)" />
    <wr-pagination [total]="total()" [(page)]="page" />
  `,
})
export class Orders {
  readonly q = wrQueryParam('q', { replaceUrl: true });
  readonly page = wrQueryParam<number>('page', { default: 1, parse: raw => Number(raw) || 1, serialize: String });
  readonly orders = httpResource<Order[]>(() => `/api/orders?q=${this.q()}&page=${this.page()}`);
}
```

## A typed parameter

A string needs no options. Any other type needs `default`, `parse` and `serialize`, and the compiler refuses one without them. The address is user input: a `parse` that throws reads as `default`.

```angular-ts
readonly tags = wrQueryParam<string[]>('tags', {
  default: [],
  parse: raw => raw.split(','),
  serialize: tags => tags.join(','),
});

readonly sort = wrQueryParam<'asc' | 'desc'>('sort', {
  default: 'asc',
  parse: raw => (raw === 'desc' ? 'desc' : 'asc'),
  serialize: String,
});

// Refused by the compiler: a number needs parse and serialize.
readonly page = wrQueryParam<number>('page', { default: 1 });
```

## Rules

| When | What happens |
| --- | --- |
| The parameter is absent | Reads as `default`. A repeated one reads its first value. |
| A write of `default` | Removes the parameter. Already absent: no navigation. |
| Several writes in one task | One navigation, across every signal. Other parameters and the fragment survive. |
| `replaceUrl` differs within one task | The navigation pushes. A replaced entry is lost; a pushed one is one more Back. |
| A navigation is in flight | The write waits, then lands on the address it produced. |
| Its navigation is cancelled or fails | The signal reads the address again. A lost write is never kept. |
| The injection context is destroyed | Following stops. A write already made is navigated, unless it was waiting for the navigation that destroyed it. |
| On the server | Reads from the router. A write moves the signal only; prerender and hydration navigate nothing. |

## API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `wrQueryParam(name, options?)` | A `WritableSignal<string>` linked to the `name` parameter. `options.default` is what an absent parameter reads as and the value that removes it; `options.replaceUrl` replaces the history entry instead of pushing one. Needs an injection context. | `(name: string, options?: WrQueryParamStringOptions) => WritableSignal<string>` | `-` |
| `wrQueryParam<T>(name, options)` | The typed form: `options.default`, `options.parse` and `options.serialize` are required. A `parse` that throws reads as `default`. `serialize` is called once for `default`, so a value that serializes like it is left out of the address too. | `<T>(name: string, options: WrQueryParamOptions<T>) => WritableSignal<T>` | `-` |
| `WrQueryParamStringOptions` | `default` (an empty string unless given) and `replaceUrl`. | `{ default?: string; replaceUrl?: boolean }` | `-` |
| `WrQueryParamOptions<T>` | `default`, `parse`, `serialize` and `replaceUrl`. | `{ default: T; parse: (raw: string) => T; serialize: (value: T) => string; replaceUrl?: boolean }` | `-` |

## See also

- [Pagination](https://ngwr.dev/reference/components/pagination) — Page navigation for a long list.
- [Tabs](https://ngwr.dev/reference/components/tabs) — Switch between panels, or between routes.
- [WrStorage](https://ngwr.dev/reference/services/storage) — Typed key-value storage over localStorage or any engine, read as a signal or written through one, safe under SSR.
