liveBook · Manning

Custom RxJS operator

As explained in Modern Angular

A custom RxJS operator is an application-defined operator that transforms or otherwise composes observable sequences.

A custom RxJS operator packages application-specific observable behavior into a reusable function. Like built-in operators, it is placed in pipe() and transforms a source observable; unlike them, it can carry business rules that would otherwise be repeated across streams. section 5.4 section 5.2

The basic shape is a function that accepts configuration and returns a function over an Observable. A simple version can wrap source.pipe(...) directly; a more concise typed version returns pipe(...) as a MonoTypeOperatorFunction. Parameters make one operator reusable across observables with different settings. section 5.4.3 section 5.4.3

Use a custom operator when it should:

  • Apply the same transformation or side effect consistently, such as logging every emitted value with an optional label. section 5.4.3
  • Encapsulate a business decision before a stream proceeds, rather than scattering that decision across call sites. section 5.4 section 5.4.3
  • Compose existing operators such as withLatestFrom, filter, map, and tap into a named operation. section 5.4.3

Gate HTTP requests by permission

A hasPermissions operator receives required permissions, reads permission state through PermissionsService, pairs each source value with the latest permission result, filters denied values, and maps allowed values back to the original value. An Angular HTTP interceptor can then apply it to employee requests, preventing unauthorized calls from proceeding. section 5.4.3 section 5.4.3

Custom operators can inject Angular dependencies directly, avoiding an explicit service parameter. Call inject() only within an injection context; otherwise, pass or arrange dependencies differently. This makes DI-backed operators practical, but ties their execution to Angular’s DI rules. section 3.2.3 section 5.4.3

Listing 5.13 Custom RxJS operator that uses dependency injection
export function hasPermissions<T>(
    permissions: Permissions[],  #1
    permissionsService = inject(PermissionsService),  #2

): MonoTypeOperatorFunction<T> {

    return pipe(
        withLatestFrom(permissionsService.hasPermissions(permissions)),  #3

        filter(([, hasPermissions]) => hasPermissions),  #4


        map(([value]) => value)      #5


    );
}

Inspect a DI-backed operator that combines permission state with a source stream, filters unauthorized emissions, and preserves the source value. section 5.4.3

How Modern Angular covers it

How deep it goes
Builds operators from the returned-function pattern through typed pipe composition and a DI-backed permission implementation.
Examples
Demonstrates logging emissions, adding a log-message parameter, and blocking employee HTTP requests without required permissions.
What you can do after
Build it from scratch as a typed, parameterized RxJS operator and apply it in an Angular HTTP interceptor.
How it connects
Connects Observable, pipe, MonoTypeOperatorFunction, dependency injection, HttpInterceptorFn, withLatestFrom, filter, map, and tap.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern Angular. The section links point to the parts of the book it draws on.