URL State makes a view shareable: query parameters hold the selected page, active tab or open navigation. Import NeuUrlStateService from @neural-ui/core/url-state and inject it in the application component that owns those decisions. It is provided in root; configure Angular Router with provideRouter(yourRoutes), without adding another service provider.
Table, Tabs and Sidebar receive applied inputs and emit proposals. The application converts validated URL values into those inputs, then writes accepted proposals back to the URL. Create each getParam signal once as a class field. No effect is needed to copy URL reads back into writes.
Search for a customer, sort a column or move to the next page. The application maps ordersPage, ordersSize, ordersSearch, ordersSort and ordersDir to NeuTableQuery. URL page numbers start at 1; Table page indices start at 0. Page size and sort values are allowlisted, and the requested page is clamped to the matching rows. This recipe persists global search, sorting and pagination; filters remain null.
queryChange is accepted with one patchParams call. Typing resets the page and replaces the current history entry; sorting and pagination add history entries. Reload the resulting URL, or use Back and Forward, to restore the applied query. The Source tab includes the shared rows, columns and bilingual labels used by the running example.
Select Activity to write detailsTab=activity. activeId is derived from a cached getParam signal; a missing or unknown value selects Summary. activeIdChange writes only an accepted tab ID. Summary removes this example's parameter with null.
Both tabs create history entries. Back and Forward update the selected panel through activeId, without emitting another URL write. Reload or share a URL ending in ?detailsTab=activity to open that panel directly.
Open navigation to write navigationOpen=true. Only that exact string opens the overlay; missing or unknown values keep it closed. The application supplies [open] and accepts closeRequested by removing the parameter. Escape, backdrop and the close control follow that same application-owned path.
Opening and closing create history entries. Back can close or reopen the Sidebar, and reloading a shared open URL restores it. opened and closed are observations, not persistence commands: writing from them would turn restored state into another navigation. This example uses overlay mode; a persistent Sidebar is always presented and does not use open to toggle its visibility.
The service exposes one readonly signal and four public methods. Writes return void and delegate navigation to Angular Router; they do not return a navigation-completion promise. Values are strings, with null reserved for removal. Unrelated query parameters are merged by setParam and patchParams.
setParam batches synchronous calls in a microtask. patchParams updates related values in one navigation and includes any queued setParam changes. Pending writes are visible through params before navigation completes; a guarded or cancelled navigation can restore the Router's actual values. Within a batch, any replaceUrl=false request makes the resulting navigation create a history entry.
Member
Type / signature
Behavior
params
readonly Signal<Params>
Reactive query parameter map, initialized from Router.url and refreshed on NavigationEnd. Includes pending writes.
getParam
getParam(key: string): Signal<string | null>
Read one key; null when absent. Cache the returned signal once. Validate URL values, including repeated parameters.
replaceUrl defaults to true: it replaces the current history entry. Pass false for deliberate actions that users should undo with Back. Each example's Reset removes only its own keys with patchParams or setParam, preserving the other examples and any unrelated parameters. clearParams removes every query parameter and should be reserved for an intentional whole-page reset.
Treat URL input as untrusted strings: validate numbers, enums and repeated parameters before supplying component inputs. These examples apply safe defaults without rewriting invalid URLs on initial render. Do not put secrets or personal data in shareable query parameters. With SSR, derive initial state from the routed request consistently on server and client; no localStorage or browser-global access is needed by these recipes.
Public Types
Inspect the definitions of types linked on this page.
import type { NeuFilterConstraint } from '@neural-ui/core/table';
import type { NeuFilterGroup } from '@neural-ui/core/table';
import type { NeuFilterExpression } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuFilterExpression<F extends string> = NeuFilterConstraint<F> | NeuFilterGroup<F>;
NeuFilterGroup.d.ts
import type { NeuFilterExpression } from '@neural-ui/core/table';
import type { NeuFilterOperator } from '@neural-ui/core/table';
import type { NeuFilterGroup } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuFilterGroup<F extends string> {
readonly children: readonly NeuFilterExpression<F>[];
readonly kind: 'group';
readonly operator: NeuFilterOperator;
}
NeuFilterOperator.d.ts
import type { NeuFilterOperator } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuFilterOperator = 'and' | 'or';
NeuSortDirection.d.ts
import type { NeuSortDirection } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuSortDirection = 'asc' | 'desc';
NeuSortEntry.d.ts
import type { NeuSortDirection } from '@neural-ui/core/table';
import type { NeuSortEntry } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuSortEntry<F extends string> {
readonly direction: NeuSortDirection;
readonly field: F;
}
NeuTableQuery.d.ts
import type { NeuFilterExpression } from '@neural-ui/core/table';
import type { NeuSortEntry } from '@neural-ui/core/table';
import type { NeuTableQuery } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableQuery<F extends string> {
readonly filters: NeuFilterExpression<F> | null;
readonly page: number;
readonly pageSize: number;
readonly search: string;
readonly sort: readonly NeuSortEntry<F>[];
}