Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/comparison/ngrx-router-store.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ Router Component Store synchronizes router state at the following router events.

## Router state serializer

NgRx Router Store uses `MinimalRouterStateSerializer` by default, offers a `FullRouterStateSerializer`, and supports a custom router state seralizer through a _serializer_ setting. Router Component Store uses a serializer similar to `MinimalRouterStateSerializer` but does not support a full or custom router state serializer.
NgRx Router Store uses `MinimalRouterStateSerializer` by default, offers a `FullRouterStateSerializer`, and supports a custom router state seralizer through a _serializer_ setting. Router Component Store uses a serializer similar to `MinimalRouterStateSerializer` and now supports custom router state serializers through the `serializer` configuration option in `provideGlobalRouterStore` and `provideLocalRouterStore`.
111 changes: 111 additions & 0 deletions packages/router-component-store/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,114 @@ export type StrictRouteParams = {
readonly [key: string]: string | undefined;
};
```

## Custom Router State Serializer

Router Component Store supports custom router state serializers, similar to NgRx Router Store. This allows you to customize how router state snapshots are serialized and stored.

### Configuration

You can provide a custom serializer when configuring global or local router stores:

#### Global Router Store with Custom Serializer

```typescript
// main.ts or app.module.ts
import { provideGlobalRouterStore, RouterStateSerializer, MinimalRouterStateSnapshot } from '@ngworker/router-component-store';
import { Injectable } from '@angular/core';
import { RouterStateSnapshot } from '@angular/router';

// Example: Custom serializer that still produces MinimalRouterStateSnapshot
// but with custom URL transformation
@Injectable()
export class CustomRouterStateSerializer implements RouterStateSerializer<MinimalRouterStateSnapshot> {
serialize(routerState: RouterStateSnapshot): MinimalRouterStateSnapshot {
// Custom serialization logic
return {
root: this.serializeRoute(routerState.root),
url: '/custom' + routerState.url, // Custom URL prefix
};
}

private serializeRoute(route: any): any {
// Implement your custom route serialization logic
// This is a simplified example - see MinimalRouterStateSerializer for full implementation
return {
params: route.params || {},
data: route.data || {},
url: route.url || [],
outlet: route.outlet || 'primary',
title: route.title,
routeConfig: route.routeConfig,
queryParams: route.queryParams || {},
fragment: route.fragment,
firstChild: route.children?.[0] ? this.serializeRoute(route.children[0]) : null,
children: route.children?.map((child: any) => this.serializeRoute(child)) || [],
};
}
}

// In your providers
providers: [
provideGlobalRouterStore({ serializer: CustomRouterStateSerializer }),
// ... other providers
]
```

#### Local Router Store with Custom Serializer

```typescript
// hero-detail.component.ts
import { Component, Injectable, inject } from '@angular/core';
import { RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import {
provideLocalRouterStore,
RouterStateSerializer,
RouterStore,
MinimalRouterStateSnapshot
} from '@ngworker/router-component-store';

@Injectable()
export class CustomLocalSerializer implements RouterStateSerializer<MinimalRouterStateSnapshot> {
serialize(routerState: RouterStateSnapshot): MinimalRouterStateSnapshot {
// Custom serialization logic that still produces MinimalRouterStateSnapshot
return {
root: this.serializeRoute(routerState.root),
url: this.transformUrl(routerState.url), // Custom URL transformation
};
}

private transformUrl(url: string): string {
// Add custom URL transformation logic
return url.toLowerCase();
}

// ... other helper methods
}

@Component({
// (...)
providers: [provideLocalRouterStore({ serializer: CustomLocalSerializer })],
})
export class HeroDetailComponent {
#routerStore = inject(RouterStore);

heroId$: Observable<string | undefined> = this.#routerStore.selectRouteParam('id');
}
```

### Important Notes

1. **Backward Compatibility**: Custom serializers must produce a structure that's compatible with `MinimalRouterStateSnapshot` if you want to use the existing `RouterStore` interface methods.

2. **Type Safety**: The `RouterStateSerializer<T>` interface is generic, allowing you to specify the return type of your serializer.

3. **Default Behavior**: If no custom serializer is provided, the default `MinimalRouterStateSerializer` is used.

### Example Use Cases

- **URL Transformation**: Modify URLs before they're stored (e.g., adding prefixes, converting to lowercase)
- **Data Enrichment**: Add timestamps, user context, or other metadata to the router state
- **Filtering**: Remove sensitive information or unnecessary data from the router state
- **Custom State Structure**: Create specialized state structures for specific application needs (while maintaining compatibility with the existing router store interface)
6 changes: 6 additions & 0 deletions packages/router-component-store/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
export * from './lib/global-router-store/provide-global-router-store';
// Serializable route state
export * from './lib/@ngrx/router-store/minimal-activated-route-state-snapshot';
export * from './lib/@ngrx/router-store/minimal-router-state-snapshot';
// LocalRouterStore
export * from './lib/local-router-store/provide-local-router-store';
// RouterStore
export * from './lib/router-store';
export * from './lib/strict-query-params';
export * from './lib/strict-route-data';
export * from './lib/strict-route-params';
// Custom serializer support
export * from './lib/router-state-serializer';
export * from './lib/router-store-config';
// MinimalRouterStateSerializer for custom implementations
export * from './lib/@ngrx/router-store/minimal_serializer';
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ import {
} from '@angular/router';
import { InternalStrictRouteData } from '../../internal-strict-route-data';
import { InternalStrictRouteParams } from '../../internal-strict-route-params';
import { RouterStateSerializer } from '../../router-state-serializer';
import { MinimalActivatedRouteSnapshot } from './minimal-activated-route-state-snapshot';
import { MinimalRouterStateSnapshot } from './minimal-router-state-snapshot';

@Injectable({
providedIn: 'root',
})
export class MinimalRouterStateSerializer {
export class MinimalRouterStateSerializer implements RouterStateSerializer<MinimalRouterStateSnapshot> {
serialize(routerState: RouterStateSnapshot): MinimalRouterStateSnapshot {
return {
root: this.#serializeRouteSnapshot(routerState.root),
Expand Down
Loading
Loading