ng-reactive-utils

Angular signal-based reactive utilities for forms, routes, browser APIs, and state management. Use when building modern Angular 20+ applications with signals instead of RxJS subscriptions.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ng-reactive-utils" with this command: npx skills add neb636/ng-reactive-utils/neb636-ng-reactive-utils-ng-reactive-utils

ng-reactive-utils

Signal-based reactive utilities for modern Angular (v20+). Convert Observable-based APIs to Signals for cleaner, more reactive code.

When to Use This Skill

Activate this skill when:

  • Working with legacy Reactive Forms (FormGroup/FormControl) and need to track form/control state as signals
  • Handling route parameters or query parameters in Angular
  • Persisting state to localStorage or sessionStorage
  • Tracking browser APIs (window size, mouse position, visibility, media queries)
  • Building any Angular 20+ application that uses signals

Important: Form Composables Are for Legacy Reactive Forms Only

The form composables (useFormValue, useControlValid, etc.) are designed for existing/legacy Reactive Forms that use FormGroup, FormControl, and FormBuilder.

DO NOT use these composables as a reason to create new forms with Reactive Forms. Angular's experimental signal-based forms are the path forward for new form development.

Use form composables when:

  • Maintaining or extending existing Reactive Forms code
  • Migrating legacy forms incrementally to signal-based patterns
  • Working in codebases that haven't adopted signal-based forms yet

For new forms, prefer Angular's signal-based forms approach when available.

Installation

npm install ng-reactive-utils

Import Pattern

All functions are exported from the main package:

import {
  useFormValid,
  useRouteParam,
  usePreviousSignal,
  useLocalStorage,
  when,
} from 'ng-reactive-utils';

API Quick Reference

Legacy Reactive Forms - FormGroup (for existing forms only)

NeedUse
Form value as signaluseFormValue(form)
Form validityuseFormValid(form)
Form errorsuseFormErrors(form)
Form statususeFormStatus(form)
Form dirty stateuseFormDirty(form)
Form touched stateuseFormTouched(form)
Form untouched stateuseFormUntouched(form)
Form pristine stateuseFormPristine(form)
Form pending stateuseFormPending(form)
Form disabled stateuseFormDisabled(form)
Complete form stateuseFormState(form)

Legacy Reactive Forms - FormControl (for existing forms only)

NeedUse
Control value as signaluseControlValue(control)
Control validityuseControlValid(control)
Control errorsuseControlErrors(control)
Control statususeControlStatus(control)
Control dirty stateuseControlDirty(control)
Control touched stateuseControlTouched(control)
Control untouched stateuseControlUntouched(control)
Control pristine stateuseControlPristine(control)
Control pending stateuseControlPending(control)
Control disabled stateuseControlDisabled(control)
Complete control stateuseControlState(control)

Route

NeedUse
Single route paramuseRouteParam('id')
Single query paramuseRouteQueryParam('search')
All route paramsuseRouteParams()
All query paramsuseRouteQueryParams()
URL fragmentuseRouteFragment()
Route datauseRouteData()

Browser APIs

NeedUse
Window dimensionsuseWindowSize()Signal<{ width, height }>
Mouse coordinatesuseMousePosition()Signal<{ x, y }>
Tab visibilityuseDocumentVisibility()Signal<boolean>
CSS media query matchuseMediaQuery(query)Signal<boolean>
Element boundsuseElementBounding(elementRef)Signal<ElementBounding>
Event listener w/ cleanupuseEventListener(event, handler, options?)
Persist to localStorageuseLocalStorage(key, defaultValue)WritableSignal<T>
Persist to sessionStorageuseSessionStorage(key, defaultValue)WritableSignal<T>

Signal Utilities

NeedUse
Previous valueusePreviousSignal(signal)Signal<T | undefined>
Run callback when predicate is truewhen(source, predicate, callback) → cancel fn
Run callback when signal is truthywhenTrue(source, callback) → cancel fn
Run callback when signal is falsywhenFalse(source, callback) → cancel fn

Utilities

NeedUse
Shared composable instancecreateSharedComposable(composableFn)

Anti-Patterns - NEVER Do This

When ng-reactive-utils is available, NEVER use these patterns:

BAD (Don't Do)GOOD (Do This Instead)
route.params.subscribe(...)useRouteParam('id')
route.queryParams.subscribe(...)useRouteQueryParam('q')
control.valueChanges.subscribe(...) (legacy forms)useControlValue(control)
control.statusChanges.subscribe(...) (legacy forms)useControlStatus(control)
form.valueChanges.subscribe(...) (legacy forms)useFormValue(form)
Manual fromEvent(window, 'resize')useWindowSize()
Manual fromEvent(document, 'mousemove')useMousePosition()
Manual previous value trackingusePreviousSignal(signal)
Manual localStorage.getItem/setItemuseLocalStorage(key, default)
Manual sessionStorage.getItem/setItemuseSessionStorage(key, default)
Manual window.matchMedia(...)useMediaQuery(query)
Manual addEventListener/removeEventListeneruseEventListener(event, handler)

Usage Examples

Route Parameter Handling

@Component({
  template: `
    <h1>User: {{ userId() }}</h1>
    <tabs [activeTab]="tab()" />
  `
})
export class UserComponent {
  userId = useRouteParam('id');
  tab = useRouteQueryParam('tab');
}

Persisting State to localStorage

@Component({...})
export class SettingsComponent {
  theme = useLocalStorage<'light' | 'dark'>('app-theme', 'light');
  // theme is a WritableSignal — reads and writes sync with localStorage automatically
}

Window Size Responsive Layout

@Component({
  template: `
    @if (windowSize().width < 768) {
      <mobile-nav />
    } @else {
      <desktop-nav />
    }
  `
})
export class LayoutComponent {
  windowSize = useWindowSize();
}

Tracking Previous Values

@Component({...})
export class AnimatedComponent {
  count = signal(0);
  previousCount = usePreviousSignal(this.count);

  direction = computed(() =>
    this.count() > (this.previousCount() ?? 0) ? 'up' : 'down'
  );
}

Reacting to Signal Changes

@Component({...})
export class UploadComponent {
  uploadStatus = signal<'idle' | 'uploading' | 'complete'>('idle');

  constructor() {
    when(this.uploadStatus, (status) => status === 'complete', () => {
      this.showSuccessToast();
    });
  }
}

Legacy Reactive Forms (for existing forms only)

Use these composables when working with existing Reactive Forms code, NOT for creating new forms:

// Only use for EXISTING legacy Reactive Forms
@Component({
  template: `
    <form [formGroup]="form">
      <input formControlName="email" />
      @if (emailErrors()?.required) {
        <span>Email is required</span>
      }
      <button [disabled]="!isValid()">Submit</button>
    </form>
  `
})
export class LegacyFormComponent {
  form = inject(FormBuilder).group({
    email: ['', [Validators.required, Validators.email]],
    password: ['', Validators.required]
  });

  isValid = useFormValid(this.form);
  emailErrors = useControlErrors(this.form.controls.email);
}

Documentation

Full documentation: https://neb636.github.io/ng-reactive-utils/

LLM-friendly docs: https://neb636.github.io/ng-reactive-utils/llms-full.txt

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

PayPilot by AGMS

Process payments, send invoices, issue refunds, manage subscriptions, and detect fraud via a secure payment gateway proxy. Use when a user asks to charge som...

Registry SourceRecently Updated
General

Poem Generator

诗歌生成助手。现代诗、俳句、对联、藏头诗、古诗翻译。Poem generator with free verse, haiku, couplets, acrostic poems, classical poetry translation. Use when you need poem generator cap...

Registry SourceRecently Updated
General

Garmin Sync

Sync activities from Garmin China to Garmin Global using local timestamps and distance to avoid duplicates in a one-way sync process.

Registry SourceRecently Updated
General

Trader Simulator

🤖 OpenClaw Skill /skills | 炒股大师模拟器 | 股市模拟交易练习 | A股/港股/美股投资学习 | 化身文主任/股神老徐/炒股养家/孙宇晨等各位大师学习投资思路 | 多智能体股票讨论群

Registry SourceRecently Updated