QueryParams

Reactive wrapper around Angular Router's query parameters. Optionally validate parameters at runtime using schema validators for type checking, type coercion, and error handling.

Usage

Basic usage

angular-ts
import { Component } from '@angular/core';
import { queryParams } from '@signality/core';

@Component({
  template: `
    <p>Search: {{ queryParams().q }}</p>
    <p>Sort: {{ queryParams().sort }}</p>
  `,
})
export class SearchPage {
  readonly queryParams = queryParams<{ q: string; sort: string }>(); 
}

With schema validation

angular-ts
import { Component } from '@angular/core';
import { queryParams } from '@signality/core';
import { z } from 'zod'; 

const schema = z.object({
  q: z.string().optional(),
  page: z.coerce.number().default(1),
});

@Component({
  template: `
    <p>Search: {{ params.value().q }}</p>
    <p>Page: {{ params.value().page }}</p>
  `,
})
export class SearchPage {
  readonly params = queryParams({ schema }); 
}

Parameters

ParameterTypeDescription
optionsQueryParamsOptions<T> | QueryParamsWithSchemaOptions<T>Optional configuration (see Options below). When schema is provided, enables validation and returns QueryParamsRef<T>.

Options

The options object extends CreateSignalOptions<T> and WithInjector:

OptionTypeDefaultDescription
equalValueEqualityFn<T>-Custom equality function (see more)
debugNamestring-Debug name for the signal (development only)
schemaQueryParamsValidator<T>-Optional. Validator schema for runtime validation. When provided, returns QueryParamsRef<T> instead of Signal<T>. See Schema validation for details.
injectorInjector-Optional injector for DI context

Return Value

The return type depends on whether a schema is provided:

Without schema

Returns Signal<T> containing the current query parameters, where T is an object with string keys and values of any type (defaults to Record<string, any>).

With schema

Returns QueryParamsRef<T> — an object with the following properties:

PropertyTypeDescription
valueSignal<T>Signal containing validated and transformed query parameters. Reading this signal throws an error if validation failed. Use isValid() to check before reading.
isValidSignal<boolean>Signal indicating whether the current query parameters are valid according to the schema. true when valid, false when validation fails.
errorSignal<unknown | null>Signal containing the validation error object, or null if the parameters are valid.

Examples

Accessing individual query params

angular-ts
import { Component, computed } from '@angular/core';
import { queryParams } from '@signality/core';

@Component({ /* ... */ })
export class SearchResults {
  readonly queryParams = queryParams<{ q?: string; page?: string }>();
  
  readonly search = computed(() => this.queryParams().q ?? ''); 
  readonly page = computed(() => Number(this.queryParams().page ?? '1')); 
}

Schema validation

Validate query parameters at runtime using schema validators like Zod. When a schema is provided, queryParams returns a QueryParamsRef object with validation status and error information.

Reading value() in error state

Reading the value() signal on a QueryParamsRef that is in an error state throws at runtime. It is recommended to guard value() reads with isValid().

angular-ts
if (params.isValid()) {
  // Safe to read params.value()
  const data = params.value();
}
angular-ts
import { Component, effect, signal } from '@angular/core';
import { queryParams } from '@signality/core';
import { z } from 'zod';

const searchSchema = z.object({
  q: z.string().min(1).optional(),
  page: z.coerce.number().int().positive().default(1),
});

@Component({ /* ... */ })
export class SearchPage {
  readonly params = queryParams({ schema: searchSchema });

  constructor() {
    effect(() => {
      if (this.params.isValid()) { 
        const { q, page } = this.params.value(); 
        this.searchProducts(q, page); 
      } 
    });
  }

  async searchProducts(q?: string, page = 1) {
    // API call implementation
  }
}

Custom validators

You can use any validator that implements the QueryParamsValidator interface:

typescript
interface QueryParamsValidator<T> {
  parse(data: unknown): T;
}
angular-ts
const pageSchema = {
  parse(data: unknown): { page: string } {
    const params = data as { page?: string };
    const page = Number(params.page);
    if (isNaN(page) || page < 1) {
      throw new Error('Page must be a positive number');
    }
    return { page };
  },
};

SSR Compatibility

On the server, the signal initializes with the query params from the snapshot.

Type Definitions

typescript
interface QueryParamsValidator<T> {
  parse(data: unknown): T;
}

interface QueryParamsRef<T> {
  readonly value: Signal<T>;
  readonly isValid: Signal<boolean>;
  readonly error: Signal<unknown | null>;
}

type QueryParamsOptions<T extends Record<string, any> = Record<string, any>> = CreateSignalOptions<T> & WithInjector;

type QueryParamsWithSchemaOptions<T extends Record<string, any> = Record<string, any>> = QueryParamsOptions<T> & {
  readonly schema: QueryParamsValidator<T>;
};

// Without schema - returns Signal<T>
function queryParams<T extends Record<string, any> = Record<string, any>>(options?: QueryParamsOptions<T>): Signal<T>;

// With schema - returns QueryParamsRef<T>
function queryParams<T extends Record<string, any> = Record<string, any>>(
  options: QueryParamsWithSchemaOptions<T>
): QueryParamsRef<T>;
  • params — Access route parameters
  • fragment — Access URL fragment
  • url — Access current URL
Edit this page on GitHub Last updated: Mar 19, 2026, 23:28:23