Skip to content

A library that adds a few utility functions for working with signals and observables together in angular, plus a bit more.

License

Notifications You must be signed in to change notification settings

stephen-moyer/ngx-signals-pack

Repository files navigation

ngx-signals-pack

A library that adds a few utility functions for working with signals and observables together in angular, plus a bit more.

Getting Started

Install

npm i ngx-signals-pack

Minimal Example

The following is a minimal example of using observableEffect, a wrapper around an effect that runs the provided function and subscribes to the returned observable. If you are unfamiliar with the new signals/effects features in angular, see here.

The value of users will be the status of loading the observable (loading, pending, loading), and eventually contain the value emitted from the searchUsers observable.

import { signal, effect } from '@angular/core';
import { observableEffect } from 'ngx-signals-pack';

// component boilerplate...

readonly query = signal({ name: 'john' })
readonly users = observableEffect(
  () => this.httpClient.searchUsers(this.query()) // promises work too!
); 
readonly _ = effect(() => {
  console.log(users());
  // ...search for john
  // { "status": "loading", value: undefined }
  // ...observable completes
  // { "status": "loaded", value: { name: 'john' } }
  //
  // ...search for bob
  // { "status": "loading", value: { name: 'john' } }
  // ...observable completes
  // { "status": "loaded", value: { name: 'bob' } }
});

searchForBob() {
  // setting query will call the function to load the observable again
  query.set({ name: 'bob' });
}

Component Example

The following shows an example of a component using observableEffect.

// ... other imports
import { observableEffect } from 'ngx-signals-pack';

@Component({
  selector: 'ngx-signals-pack-example',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule],
  template: `
    <!-- Generally you would create a reusable component to represent the different states -->
    <button (click)="reload()">Reload</button>
    <div *ngIf="example().status === 'pending'">Waiting...</div>
    <div *ngIf="example().status === 'loading'">Loading...</div>
    <div *ngIf="example().status === 'error'">Error: {{ example().error }}</div>
    <div *ngIf="example().status === 'loaded'">Value: {{ example().value }}</div>
    
    <hr />

    <button (click)="increment()">Increment</button>
    <div *ngIf="reactiveExample().status === 'pending'">Waiting...</div>
    <div *ngIf="reactiveExample().status === 'loading'">Loading...</div>
    <div *ngIf="reactiveExample().status === 'error'">Error: {{ example().error }}</div>
    <div *ngIf="reactiveExample().status === 'loaded'">Value: {{ example().value }}</div>
  `,
  styleUrl: './ngx-signals-pack-example.component.scss',
})
export class NgxSignalsExampleComponent {
  // or httpClient.get(), or fetch(). any ObservableInput type can be returned.
  // when the component is destroyed, the observable will be unsubscribed
  readonly example = observableEffect(() => of(1).pipe(delay(1000)));

  reload() {
    this.example.load();
  }

  // the function returning an observable will be rerun everytime dependency changes
  // if dependency changes very quickly, before the observable completes,
  // it will be cancelled and the function run again returning a new 
  // observable to subscribe to.
  readonly dependency = signal(1);
  readonly reactiveExample = observableEffect(() => 
    of(this.dependency()).pipe(delay(1000))
  );

  increment() {
    this.dependency.update((val) => ++val);
  }
}

Please see the interactive documentation for more examples.

Documentation

Interactive example documentation is available here

About

A library that adds a few utility functions for working with signals and observables together in angular, plus a bit more.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages