combineFrom

The combineFrom function takes an array or object of Observables or Signals and produces a Signal that emits the aggregated value from these sources. This function operates akin to combineLatest, yet it extends its functionality to include Signals in the amalgamation process. Normally, it requires invocation within an injection context. However, it offers the flexibility to be called outside of such contexts by providing the Injector within the third argument options object. In cases where an Observable doesn't emit synchronously, you can utilize the startWith operator to modify the initial emitted value, or alternatively specify an initialValue within the options object.

Examples

Example 1: Basic Usage

Combine multiple signals or observables:

import {combineFrom} from 'ngx-lift';

export class CombineFromComponent {
  a = signal(1);
  b$ = new BehaviorSubject(2);

  // array type
  combinedArray = combineFrom([this.a, this.b$]); // [1, 2]

  // object type
  combinedObject = combineFrom({a: this.a, b: this.b$}); // {a: 1, b: 2}
}

Example 2: With RxJS Pipe Operator

Pass an RxJS pipe operator to manipulate the emitted values:

import {combineFrom} from 'ngx-lift';

export class CombineFromComponent {
  a = signal(1);
  b$ = new BehaviorSubject(2);

  combineOperator = combineFrom(
    [this.a, this.b$],
    pipe(switchMap(([a, b]) => of(a + b))),
  ); // 3
}

Example 3: Handle Asynchronous Code

Use startWith or initialValue option to handle async observables:

import {combineFrom} from 'ngx-lift';

export class CombineFromComponent {
  a = signal(1);
  b$ = new BehaviorSubject(2);

  // initially 0, after 1s value changes to 3
  combinedWithInitialValue = combineFrom(
    [this.a, this.b$],
    pipe(
      switchMap(
        ([a, b]) => of(a + b).pipe(delay(1000)), // later async emit value
      ),
    ),
    {initialValue: 0}, // pass the initial value of the resulting signal
  );

  // initially 0, after 1s value changes to 3
  combinedStartWith = combineFrom(
    [this.a, this.b$],
    pipe(
      switchMap(([a, b]) => of(a + b).pipe(delay(1000))),
      startWith(0),
    ),
  );
}

Example 4: Real Example - Get Filtered Data

In the "get users" request below, the response returns 9 users. We intend to display only the first 3 users. Any client-side filtering, sorting can use the same strategy.

thumbnail
Name
Vedat Candan
Gender
male
thumbnail
Name
Domingo Delgado
Gender
male
thumbnail
Name
Louis Sanders
Gender
male
import {combineFrom, createAsyncState} from 'ngx-lift';
import {Component, inject, signal} from '@angular/core';
import {pipe, switchMap} from 'rxjs';
import {of} from 'rxjs';
import {SpinnerComponent, AlertComponent} from 'clr-lift';

@Component({
  imports: [SpinnerComponent, AlertComponent],
  template: `
    @if (usersState()?.isLoading) {
      <cll-spinner />
    }

    @if (usersState()?.error; as error) {
      <cll-alert [error]="error" />
    }

    @if (usersState()?.data; as users) {
      <div class="card-grid">
        @for (user of users; track user.id.value) {
          <app-user-card [user]="user" />
        }
      </div>
    }
  `
})
export class CombineFromComponent {
  private userService = inject(UserService);
  count = signal(3);

  usersState = combineFrom(
    [this.count, this.userService.getUsers({results: 9})],
    pipe(
      switchMap(([count, users]) => of(users.results.slice(0, count))),
      createAsyncState(),
    ),
  );
}

API Reference

combineFrom

Combines multiple Observables or Signals into a single Signal that emits aggregated values, similar to combineLatest but with Signal support.

Signature

combineFrom<T>(
  sources: Record<string, Observable<T> | Signal<T>> | Array<Observable<T> | Signal<T>>,
  operator?: OperatorFunction,
  options?: CombineFromOptions
): Signal<T[] | Record<string, T>>

Parameters

  • sources: Record<string, Observable<T> | Signal<T>> | Array<Observable<T> | Signal<T>>

    An object or array of Observables or Signals to combine. When an object is provided, the result will be an object with the same keys.

  • operator?: OperatorFunction

    (Optional) An RxJS pipe operator to manipulate the emitted values before they are emitted.

  • options?: CombineFromOptions

    (Optional) Configuration options including initialValue and injector.

Returns

A signal that emits an array or object (depending on input type) containing the latest values from all source observables and signals.