combineLatestEager

The RxJS operator combineLatest requires all sources to emit at least once, which can be problematic when using Subject sources that may not emit initially. combineLatestEager extends combineLatest by automatically adding startWith(null) for each Subject in the sources, ensuring the combined observable initializes properly. You can also set the second parameter to true to append startWith(null) for all source observables, which is useful when dealing with numerous observables where initial emissions are not guaranteed.

Examples

Example 1: Basic Usage

Combine observables including Subjects that may not emit initially:

import {combineLatestEager} from 'ngx-lift';
import {of, Subject} from 'rxjs';

export class MyComponent {
  today$ = of(new Date());
  private showAction = new Subject<void>();

  // Using RxJS combineLatest won't work because showAction won't emit initial value
  // combineLatestEager automatically adds startWith(null) for Subject sources
  vm$ = combineLatestEager({
    today: this.today$,
    action: this.showAction$,
  });
}

Example 2: Complete Example with Template

Complete example showing how to use combineLatestEager with async pipe in templates:

Today is . Who is our today's rock star?

@if (vm$ | async; as vm) {
  <p>
    Today is <time>{{ vm.today | date }}</time>. Who is our today's rock star?
    <button (click)="showRockStar()" class="btn btn-outline">Unveil</button>
  </p>

  @if (vm.rockStarState?.error; as error) {
    <cll-alert [error]="error" />
  }
  @if (vm.rockStarState?.isLoading) {
    <cll-spinner />
  }
  @if (vm.rockStarState?.data; as rockStar) {
    <p class="!text-xl">{{ rockStar.name }}</p>
  }
}
import {AlertComponent, SpinnerComponent} from 'clr-lift';
import {combineLatestEager, switchMapWithAsyncState} from 'ngx-lift';
import {inject} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {of, Subject} from 'rxjs';

export class RockStarComponent {
  today$ = of(new Date());

  private showStarAction = new Subject<void>();
  private http = inject(HttpClient);

  rockStarState$ = this.showStarAction.pipe(
    switchMapWithAsyncState(() => this.http.get<{name: string}>('https://jsonplaceholder.typicode.com/users/1')),
  );

  // Using RxJS combineLatest won't work because showStarAction won't emit initial value until button click
  vm$ = combineLatestEager({today: this.today$, rockStarState: this.rockStarState$});

  showRockStar() {
    this.showStarAction.next();
  }
}

API Reference

combineLatestEager

Combines multiple observables like combineLatest, but automatically adds startWith(null) for Subject sources to ensure proper initialization.

Signature

combineLatestEager<T>(
  sources: Record<string, Observable<T>> | Observable<T>[],
  startWithAll?: boolean
): Observable<T[] | Record<string, T>>

Parameters

  • sources: Record<string, Observable<T>> | Observable<T>[]

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

  • startWithAll?: boolean

    (Optional) When set to true, appends startWith(null) for all source observables, not just Subjects. Defaults to false.

    Useful when dealing with numerous observables where it's challenging to distinguish which ones lack initial emissions.

Returns

An observable that emits an array or object (depending on input type) containing the latest values from all source observables.