Skip to content

Introduction

NG Reactive Utils is a collection of composables for modern Angular applications. These utilities eliminate boilerplate and make working with signals more productive.

What is it?

A utility library that provides:

  • Form & Route utilities - Convert observables to signals without repetitive toSignal() calls
  • Browser APIs - Window size, mouse position, storage, media queries, and more
  • Signal utilities - Track previous values, react to signal state changes, and share composable instances across components

Quick Example

Read a route parameter and react to window size with one line each:

typescript
import { Component, computed } from '@angular/core';
import { useRouteParam, useWindowSize } from 'ng-reactive-utils';

@Component({
  selector: 'user-profile',
  template: `
    <h1>User: {{ userId() }}</h1>
    @if (isMobile()) {
      <mobile-layout />
    } @else {
      <desktop-layout />
    }
  `,
})
export class UserProfileComponent {
  userId = useRouteParam('id');
  windowSize = useWindowSize();
  isMobile = computed(() => this.windowSize().width < 768);
}

Why Use It?

Without NG Reactive Utils:

typescript
// Repetitive toSignal() calls everywhere
formValue = toSignal(form.valueChanges, { initialValue: form.value });
formValid = toSignal(form.statusChanges.pipe(map(() => form.valid)), { initialValue: form.valid });
userId = toSignal(route.params.pipe(map(p => p['id'])), { initialValue: route.snapshot.params['id'] });

With NG Reactive Utils:

typescript
// Clean, readable utilities
formState = useFormState(this.form);  // value(), valid(), dirty(), etc.
userId = useRouteParam('id');

Without NG Reactive Utils:

typescript
// Noisy effects with easy-to-forget untracked()
effect(() => {
  if (this.isOpen()) {
    untracked(() => {
      this.copy.set(cloneDeep(this.data()));
    });
  }
});

With NG Reactive Utils:

typescript
// Intent is obvious, untracked handled automatically
onOpen = whenTrue(this.isOpen, () => {
  this.copy.set(cloneDeep(this.data()));
});

Key Benefits

  • Less boilerplate - Replace repetitive toSignal() calls with clean utilities
  • Type-safe - Full TypeScript support with proper inference
  • Signal-first - Built for Angular's modern reactivity system
  • Tree-shakable - Import only what you need

What's Available

Next Steps

Ready to get started?

  1. Install the library
  2. Understand core concepts
  3. Explore the available composables

Released under the MIT License.