Pipes
All pipes in @dasch-ng/utils are standalone and can be imported directly into your components. They provide type-safe transformations for common operations.
Installation
npm install @dasch-ng/utilsor with bun:
bun add @dasch-ng/utilsOverview
The library includes over 15 standalone pipes organized into the following categories:
- Array Manipulation: Transform and reorder arrays
- Collection Utilities: Work with iterables and collections
- Object Utilities: Extract and transform object properties
- Type Checking: Runtime type guards for templates
- Formatting: Format values for display
- Text: Truncate and highlight text
- Symbol Utilities: Work with JavaScript symbols
Array Manipulation Pipes
ReversePipe
Reverses the order of elements in an array.
Usage:
import { ReversePipe } from '@dasch-ng/utils';
@Component({
imports: [ReversePipe],
template: `
@for (item of items | reverse; track item) {
<div>{{ item }}</div>
}
`
})Example:
items = ['a', 'b', 'c'];
// Template output: 'c', 'b', 'a'JoinPipe
Joins array elements into a string with a separator.
Usage:
import { JoinPipe } from '@dasch-ng/utils';
@Component({
imports: [JoinPipe],
template: `
<p>{{ tags | join:', ' }}</p>
`
})Example:
tags = ['angular', 'typescript', 'nx'];
// Output: "angular, typescript, nx"NthPipe
Returns the nth element from an array (supports negative indices).
Usage:
import { NthPipe } from '@dasch-ng/utils';
@Component({
imports: [NthPipe],
template: `
<p>First: {{ items | nth:0 }}</p>
<p>Last: {{ items | nth:-1 }}</p>
`
})Example:
items = ['a', 'b', 'c'];
// nth:0 → 'a'
// nth:-1 → 'c'SortByPipe
Sorts an array by a specified property or function.
Usage:
import { SortByPipe } from '@dasch-ng/utils';
@Component({
imports: [SortByPipe],
template: `
@for (user of users | sortBy:'name'; track user.name) {
<div>{{ user.name }}</div>
}
`
})Example:
users = [
{ name: 'Charlie', age: 30 },
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 35 },
];
// Sorted by name: Alice, Bob, CharlieCollection Utilities
SizePipe
Returns the size/length of a collection (arrays, strings, Maps, Sets).
Usage:
import { SizePipe } from '@dasch-ng/utils';
@Component({
imports: [SizePipe],
template: `
<p>Items: {{ items | size }}</p>
<p>Text length: {{ text | size }}</p>
`
})Example:
items = [1, 2, 3]; // size: 3
text = 'hello'; // size: 5
mySet = new Set([1, 2, 3]); // size: 3IncludesPipe
Checks if a collection includes a value.
Usage:
import { IncludesPipe } from '@dasch-ng/utils';
@Component({
imports: [IncludesPipe],
template: `
@if (roles | includes:'admin') {
<p>Admin panel</p>
}
`
})Example:
roles = ['user', 'editor', 'admin'];
// roles | includes:'admin' → true
// roles | includes:'superadmin' → falseIncludedInPipe
Checks if a value is included in a collection (inverse of includes).
Usage:
import { IncludedInPipe } from '@dasch-ng/utils';
@Component({
imports: [IncludedInPipe],
template: `
@if (currentRole | includedIn:allowedRoles) {
<p>Authorized</p>
}
`
})Example:
currentRole = 'admin';
allowedRoles = ['admin', 'editor'];
// 'admin' | includedIn:allowedRoles → trueWithoutPipe
Returns the items of an array or other iterable that are not among the given values (===).
[1, 2, 3, 2] | without:2 // → [1, 3]
tags | without:selectedTag // all other tagsValuesPipe
Values of a Map, Set or plain object as an array, in insertion order. Unlike keyvalue, it neither sorts nor wraps entries.
@for (user of usersById | values; track user.id) {
<li>{{ user.name }}</li>
}Object Utilities
PropPipe
Extracts a property value from an object (supports nested paths).
Usage:
import { PropPipe } from '@dasch-ng/utils';
@Component({
imports: [PropPipe],
template: `
<p>{{ user | prop:'name' }}</p>
<p>{{ user | prop:'address.city' }}</p>
`
})Example:
user = {
name: 'John',
address: {
city: 'Berlin',
},
};
// user | prop:'name' → 'John'
// user | prop:'address.city' → 'Berlin'OmitPipe
Shallow copy of an object without the given keys.
<pre>{{ user | omit: 'password' : 'token' | json }}</pre>ParseJsonPipe
Parses a JSON string; returns null instead of throwing for invalid JSON or non-string input.
@let settings = row.settingsJson | parseJson; @if (settings) {
<pre>{{ settings | json }}</pre>
}Type Checking Pipes
IsNilPipe
Checks if a value is null or undefined.
Usage:
import { IsNilPipe } from '@dasch-ng/utils';
@Component({
imports: [IsNilPipe],
template: `
@if (data | isNil) {
<div>No data available</div>
}
`
})Example:
null | isNil; // → true
undefined | isNil; // → true
0 | isNil; // → false
'' | isNil; // → falseIsNullPipe
Checks if a value is strictly null.
Usage:
import { IsNullPipe } from '@dasch-ng/utils';
@Component({
imports: [IsNullPipe],
template: `
@if (value | isNull) {
<div>Value is null</div>
}
`
})Example:
null | isNull; // → true
undefined | isNull; // → falseIsUndefinedPipe
Checks if a value is strictly undefined.
Usage:
import { IsUndefinedPipe } from '@dasch-ng/utils';
@Component({
imports: [IsUndefinedPipe],
template: `
@if (value | isUndefined) {
<div>Value is undefined</div>
}
`
})Example:
undefined | isUndefined; // → true
null | isUndefined; // → falseIsEmptyPipe
Checks if a collection or value is empty.
Usage:
import { IsEmptyPipe } from '@dasch-ng/utils';
@Component({
imports: [IsEmptyPipe],
template: `
@if (items | isEmpty) {
<div>No items</div>
}
`
})Example:
[] | isEmpty // → true
'' | isEmpty // → true
{} | isEmpty // → true
[1, 2] | isEmpty // → falseNotPipe
Negates a boolean value.
Usage:
import { NotPipe } from '@dasch-ng/utils';
@Component({
imports: [NotPipe],
template: `
@if (isHidden | not) {
<div>Content visible</div>
}
`
})Example:
true | not; // → false
false | not; // → trueFormatting Pipes
DecimalBytesPipe
Formats byte values into human-readable sizes (KB, MB, GB, etc.).
Usage:
import { DecimalBytesPipe } from '@dasch-ng/utils';
@Component({
imports: [DecimalBytesPipe],
template: `
<p>File size: {{ fileSize | decimalBytes }}</p>
<p>With precision: {{ fileSize | decimalBytes:3 }}</p>
`
})Example:
1024 | decimalBytes // → "1.02 KB"
1536000 | decimalBytes // → "1.54 MB"
1536000 | decimalBytes:3 // → "1.536 MB"
0 | decimalBytes // → "0 B"BinaryBytesPipe
The base-1024 counterpart to decimalBytes, with IEC units (KiB, MiB, GiB, …). Use it where sizes follow memory or file-system conventions. Same behaviour for 0, precision and invalid input as decimalBytes.
1024 | binaryBytes; // → "1 KiB"
1536 | binaryBytes; // → "1.5 KiB"
1000000 | binaryBytes; // → "976.56 KiB"
10485760 | binaryBytes; // → "10 MiB"Text Pipes
TruncateTextPipe
Shortens text to at most limit characters (default 160) plus …, cutting at the last space before the limit. If that space is in the first half, it cuts at the limit.
import { TruncateTextPipe } from '@dasch-ng/utils';
@Component({
imports: [TruncateTextPipe],
template: `<p>{{ description | truncateText: 120 }}</p>`,
})'The quick brown fox jumps' | truncateText:18 // → "The quick brown…"
'short' | truncateText:18 // → "short"MiddleTruncatePipe
Splits a string into { head, tail } so the ellipsis lands in the middle and the end stays visible, for example the take number and extension of a filename. The cut goes to a delimiter (_, -, ., space) within the last 16 characters, otherwise the tail is 6 characters. Graphemes (emoji, accents) are never split.
import { MiddleTruncatePipe } from '@dasch-ng/utils';
@Component({
imports: [MiddleTruncatePipe],
template: `
@let name = file.name | middleTruncate;
<span class="name" [title]="file.name">
<span class="head">{{ name.head }}</span><span class="tail">{{ name.tail }}</span>
</span>
`,
styles: `
.name { display: flex; min-width: 0; }
.head { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tail { flex-shrink: 0; white-space: pre; }
`,
})'20260901_Concert_Hamburg_Cam3_0042.mov' | middleTruncate;
// → { head: '20260901_Concert_Hamburg', tail: '_Cam3_0042.mov' }
// renders as "20260901_Conc…_Cam3_0042.mov" in a narrow columnHighlightPipe
Splits text into { text, match } segments for a search term (case-insensitive, matched literally). The template renders the matches, so there is no innerHTML and nothing to sanitize.
import { HighlightPipe } from '@dasch-ng/utils';
@Component({
imports: [HighlightPipe],
template: `
@for (part of label | highlight: query(); track $index) {
@if (part.match) {<mark>{{ part.text }}</mark>} @else {{{ part.text }}}
}
`,
})'Stadium light' | highlight:'stad'
// → [{ text: 'Stad', match: true }, { text: 'ium light', match: false }]UpperFirstPipe
Uppercases the first character with the rules of LOCALE_ID (or a locale argument) and leaves the rest unchanged. Combine with lowercase to capitalize.
'hello world' | upperFirst // → "Hello world"
'HELLO' | lowercase | upperFirst // → "Hello"
'istanbul' | upperFirst:'tr' // → "İstanbul"Symbol Utilities
SymbolKeyForPipe
Returns the global symbol key for a symbol.
Usage:
import { SymbolKeyForPipe } from '@dasch-ng/utils';
@Component({
imports: [SymbolKeyForPipe],
template: `
<p>Symbol key: {{ mySymbol | symbolKeyFor }}</p>
`
})Example:
const mySymbol = Symbol.for('app.config');
mySymbol | symbolKeyFor; // → 'app.config'Common Patterns
Chaining Pipes
Pipes can be chained together for complex transformations:
import { ReversePipe, JoinPipe } from '@dasch-ng/utils';
@Component({
imports: [ReversePipe, JoinPipe],
template: ` <p>{{ items | reverse | join: ', ' }}</p> `,
})
export class ExampleComponent {
items = ['a', 'b', 'c'];
// Output: "c, b, a"
}Conditional Rendering
Type checking pipes work great with @if:
import { IsNilPipe, IsEmptyPipe } from '@dasch-ng/utils';
@Component({
imports: [IsNilPipe, IsEmptyPipe],
template: `
@if (data | isNil) {
<div>Loading...</div>
}
@if (items | isEmpty) {
<div>No items found</div>
}
`
})Working with Objects
Extract and display nested properties:
import { PropPipe } from '@dasch-ng/utils';
@Component({
imports: [PropPipe],
template: `
@for (user of users; track user) {
<div>
<h3>{{ user | prop:'profile.name' }}</h3>
<p>{{ user | prop:'profile.email' }}</p>
</div>
}
`
})Module Support
While all pipes are provided as standalone components, a legacy NgUtilsModule is also available that exports all pipes:
import { NgUtilsModule } from '@dasch-ng/utils';
@NgModule({
imports: [NgUtilsModule],
})
export class LegacyModule {}Recommended: Use standalone pipes directly for better tree-shaking and modern Angular patterns.
API Reference
Complete TypeDoc API documentation: dasch.ng/api/@dasch-ng/utils
Source Code
View the source code on GitHub.