A collection of Angular utilities and libraries
npm install @telperion/ng-packImport: @telperion/ng-pack/common
Common Angular pipes and directives for key-value data structures (Map, Set, plain objects), template iteration, and element observation.
- π
keyspipe β extract keys from any key-value structure - π¦
valuespipe β extract values from any key-value structure - π
entriespipe β extract entries as{ key, value }objects - π
timespipe β generate[0, 1, ..., n-1]array for repeating template blocks - π
tngObserveSizedirective β observe element size viaResizeObserverwith signal-based API - οΏ½
*tngUnlessstructural directive β render a template when the expression is falsy (inverse of*ngIf) - οΏ½πΊοΈ Supports
Map,Set, and plain objects - π― Full type inference with overloaded signatures
- π‘οΈ Null-safe β returns
[]fornull/undefined
import { Component } from '@angular/core';
import { EntriesPipe } from '@telperion/ng-pack/common';
@Component({
selector: 'app-example',
standalone: true,
imports: [EntriesPipe],
template: `
@for (entry of user | entries; track entry.key) {
<div>{{ entry.key }}: {{ entry.value }}</div>
}
`
})
export class ExampleComponent {
user = { name: 'Alice', role: 'Admin' };
}Import: @telperion/ng-pack/storage-signals
Angular signals-based wrapper for browser's localStorage, sessionStorage, and cookies with reactive updates.
- π Signal-based API integrated with Angular's signal system
- π Reactive updates automatically synced across components
- π― Nested property access using dot notation
- πͺ Support for localStorage, sessionStorage, and cookies
- π Namespaced storage organization
- πͺ Full cookie configuration (secure, sameSite, maxAge, etc.)
- π Cross-instance synchronization for cookie storage
import { ApplicationConfig } from '@angular/core';
import { provideLocalStorage } from '@telperion/ng-pack/storage-signals';
export const appConfig: ApplicationConfig = {
providers: [
provideLocalStorage('my-app'),
]
};import { Component } from '@angular/core';
import { localStorageSignal } from '@telperion/ng-pack/storage-signals';
@Component({
selector: 'app-settings',
template: `
<div>
<p>Theme: {{ theme() }}</p>
<button (click)="theme.set('dark')">Dark Mode</button>
</div>
`
})
export class SettingsComponent {
// Access nested properties with dot notation
theme = localStorageSignal<string>('settings', 'ui.theme');
}Cookie Storage:
import { ApplicationConfig } from '@angular/core';
import { provideCookieStorage } from '@telperion/ng-pack/storage-signals';
export const appConfig: ApplicationConfig = {
providers: [
provideCookieStorage('my-app', {
secure: true,
sameSite: 'strict',
maxAge: 86400 // 24 hours
}),
]
};import { Component } from '@angular/core';
import { cookieStorageSignal } from '@telperion/ng-pack/storage-signals';
@Component({
selector: 'app-auth',
template: `
<div>
@if (authToken()) {
<button (click)="authToken.delete()">Logout</button>
} @else {
<button (click)="authToken.set('token123')">Login</button>
}
</div>
`
})
export class AuthComponent {
// Cookie with custom expiry
authToken = cookieStorageSignal<string>('auth', 'token', {
maxAge: 3600 // 1 hour
});
}Import: @telperion/ng-pack/sse-client
Angular service for Server-Sent Events (SSE) with RxJS Observables and HttpClient-inspired interceptors.
- π Observable-based API integrated with RxJS ecosystem
- π HttpClient-inspired interceptor chain for request manipulation
- π― Type-safe with full generic support
- β‘ EventSource wrapper with automatic cleanup
- π Real-time streaming data updates
- π¨ Feature-based configuration
import { ApplicationConfig } from '@angular/core';
import { provideSseClient, withSseInterceptors, withBaseInit } from '@telperion/ng-pack/sse-client';
export const appConfig: ApplicationConfig = {
providers: [
provideSseClient(
withBaseInit({ withCredentials: true }),
withSseInterceptors(loggingInterceptor, authInterceptor)
),
]
};import { Component, inject } from '@angular/core';
import { SseClient } from '@telperion/ng-pack/sse-client';
import { AsyncPipe } from '@angular/common';
interface StockUpdate {
symbol: string;
price: number;
change: number;
}
@Component({
selector: 'app-stock-ticker',
template: `
<div>
<h2>Live Stock Prices</h2>
@if (stockUpdates$ | async; as update) {
<div class="stock-card">
<span>{{ update.symbol }}: \${{ update.price }}</span>
<span [class.positive]="update.change > 0">
{{ update.change > 0 ? '+' : '' }}{{ update.change }}%
</span>
</div>
}
</div>
`,
standalone: true,
imports: [AsyncPipe]
})
export class StockTickerComponent {
private sseClient = inject(SseClient);
// Start SSE connection and get Observable stream
stockUpdates$ = this.sseClient.start<StockUpdate>('/api/stocks/stream');
}Import: @telperion/ng-pack/fetcher-signal
Reactive, signal-based HTTP fetcher for Angular built on top of HttpClient and Angular signals.
- π¦ Signal-first API β the result is a
Signal<T>you read directly in templates - π Reactive options β pass signals, observables, or promises and the request re-runs automatically
- π£οΈ Declarative
:namepath parameters and query parameters (RecordorHttpParams) β οΈ Built-inerrorandloadingsignals- π§―
fallbackvalue used as initial state and on error - π Manual
reload()to re-run the current request β returns aPromise<void>that resolves with the next response - β³
loadedpromise βawaitthe next response without subscribing to signals
import { Component, computed, signal } from '@angular/core';
import { fetcherSignal } from '@telperion/ng-pack/fetcher-signal';
interface User { id: number; name: string; }
@Component({
selector: 'app-users',
standalone: true,
template: `
<input [value]="search()" (input)="search.set($any($event.target).value)" />
@if (users.loading()) {
<p>Loadingβ¦</p>
} @else {
<ul>
@for (user of users(); track user.id) {
<li>{{ user.name }}</li>
}
</ul>
}
`
})
export class UsersComponent {
search = signal('');
users = fetcherSignal<User[]>({
url: '/api/users',
queryParams: computed(() => ({ q: this.search() })),
fallback: []
});
}Import: @telperion/ng-pack/template-signal-forms
π§ Under Construction
Signal-based forms utilities for Angular template-driven forms.
Import: @telperion/ng-pack/utils
Angular utility functions and plugins for enhanced development experience.
- π― Event modifier syntax for templates (
.pd,.sp) - π Directive-as-service provider utility
- π Promise-based HTTP client with tuple error handling
- οΏ½ Unified
toSignalβ convert values, Promises, or Observables to Signals - οΏ½π¦ Tree-shakeable and type-safe
- β‘ Zero dependencies
Event Modifiers Plugin
import { provideEventModifiersPlugin } from '@telperion/ng-pack/utils';
bootstrapApplication(AppComponent, {
providers: [provideEventModifiersPlugin()]
});<!-- Prevent default and stop propagation with modifiers -->
<form (submit.pd)="onSubmit()">...</form>
<div (click.sp)="handleClick()">...</div>
<button (click.pd.sp)="handleButtonClick()">Click me</button>Construct Fetcher
import { Component } from '@angular/core';
import { constructFetcher } from '@telperion/ng-pack/utils';
@Component({
selector: 'app-example',
template: `<button (click)="fetchData()">Fetch Data</button>`
})
export class ExampleComponent {
private fetcher = constructFetcher();
async fetchData() {
const [error, response] = await this.fetcher.get('/api/data');
if (error) {
console.error('Error:', error);
return;
}
console.log('Data:', response);
}
}Provide Service Directive
import { provideServiceDirective } from '@telperion/ng-pack/utils';
// Create an injection token
export const ParentService = new InjectionToken<ParentDirective>("ParentService");
// Provide directive as service
@Directive({
selector: '[parent]',
providers: [provideServiceDirective(ParentService, ParentDirective)],
})
export class ParentDirective { }
// Inject in child
@Directive({ selector: '[child]' })
export class ChildDirective {
private parent = inject(ParentService);
}Run pnpm nx test ng-pack to execute the unit tests.
Run pnpm nx build ng-pack to build the library.
This library is part of the Telperion monorepo.