What is the best way to ensure observables in a template (using async pipe) are fully subscribed to before executing any initialization code?

I am facing an issue with my HTTP service that returns information based on a given item ID. The data is fetched using a Subject, which receives the initial data in the ngOnInit method.

To display the returned data in the HTML, I utilize the async pipe.

The problem arises when the async pipe has not subscribed to the observables before I call selections.next with the first item ID, causing it not to be displayed during initialization.

Is there a way to ensure that the async pipe subscribes to the Observable before sending the initial data to the subject for the first HTTP request?

I have experimented with various lifecycle hooks, but none seem to resolve the issue.

import { Component, OnInit } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Subject } from "rxjs/Subject";

import { ExampleService } from "./example.service";

import "rxjs/add/operator/switchMap";

@Component({
  template: `
    <div>
      <div *ngFor="let time of times | async">{{ time }}</div>
    </div>
  `,
})
export class ExampleComponent implements OnInit {

  times: Observable<string[]>;

  constructor(
    private exampleService: ExampleService
  ) { }

  ngOnInit() {

    var itemIds = new Subject<number>();

    this.times = itemIds
      .switchMap(itemId => this.exampleService.getData(itemId))
      .map(data => this.calculateTimes(data));

    // Provide an item ID to the subject.
    // This is also performed periodically as well as
    // during initialization.
    itemIds.next(10);
  }

  calculateTimes(data: string[]) {
    /*
     * Some processing code.
    */

    return data;
  }
}

Answer №1

Consider using a behavior subject in place of a regular subject.

A behavior subject retains its last value and transmits it to new subscribers upon subscription.

import { BehaviorSubject } from "rxjs/BehaviorSubject";


var itemIds = new BehaviorSubject<number>(null);

Initializing the behavior subject with a value is necessary. It helps address timing issues when you are uncertain which will come first, your value or your subscriber.

To prevent duplicate calls, you can implement a local store pattern:

times: BehaviorSubject<string[]> = new BehaviorSubject<string[]>();


var itemIds = new Subject<number>();

itemIds.switchMap(itemId => this.exampleService.getData(itemId))
    .map(data => this.calculateTimes(data)).subscribe(this.times);

This approach ensures that the only subscriber to the HTTP call is the behavior subject that you subscribe to in the template.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular displays the error message TS2339, stating that the property 'handleError' is not found on the 'HeroService' type

Hey everyone, I know there are already a few questions out there about Typescript compilation errors, but I'm facing a unique challenge that I can't quite figure out. I'm currently working on the Angular Tour of Heroes app and trying to com ...

Adjust the component suppliers based on the @input

If I were to implement a material datepicker with a selection strategy, I would refer to this example There are instances where the selection strategy should not be used. The challenge lies in setting the selection strategy conditionally when it is insta ...

Simple Steps to View Angular Logs in Terminal

Upon initializing my Angular project, I utilized the npm start command to kickstart the application. The console.log() function displays logs exclusively in the browser console window. Is there a way to view these logs in the terminal window? ...

"Optimize Your Data with PrimeNG's Table Filtering Feature

I'm currently working on implementing a filter table using PrimeNG, but I'm facing an issue with the JSON structure I receive, which has multiple nested levels. Here's an example: { "id": "123", "category": "nice", "place": { "ran ...

Struggling to grasp the process of incorporating OAuth into both a REST API and a Single Page Application

I am currently working on integrating my SPA, DjangoRestframework, and auth0. My understanding is that the user registration process, as well as logging in and out, are all handled by Angular. Here are some key questions I need assistance with: 1. Aft ...

Unit Testing in Vue.JS: The original function remains active even after using sinon.stub()

While unit testing my components (which are coded using TypeScript along with vue-class-component), I am utilizing Sinon to stub API calls. However, even after adding the stub to the test, the original method is still being invoked instead of returning the ...

Is there an issue with validation when using looped radio buttons with default values in data-driven forms?

Within my reactive form, I am iterating over some data and attempting to pre-set default values for radio buttons. While the default values are being successfully set, the validation is not functioning as expected. <fieldset *ngIf="question.radioB ...

Having trouble retrieving response headers in Angular 5

After sending a post request to a server, I receive a response with two crucial headers for the client: username and access-token. The Chrome debug tool's Network Tab displays the data from the response like this: In addition, I attempt to log the re ...

Utilizing Angular Material's <mat-selection-list> and <mat-list-option> components seamlessly between different sections of a template

How can a <mat-list-option> declared in component sub subscribe to a <mat-selection-list> outside of component sub (for example, in component app)? (Unfortunately, I couldn't get Stackblitz to work due to my corporate's proxy restric ...

What is the best way to specify types for a collection of objects that all inherit from a common class?

I am new to typescript and may be asking a beginner question. In my scenario, I have an array containing objects that all extend the same class. Here is an example: class Body{ // implementation } class Rectangle extends Body{ // implementation } class ...

Guide on updating a property key in Firebase real-time database with Angular 7

Is it possible to modify the key of a property in my firebase database that I have been struggling with? ...

Angular 4 allows you to assign unique colors to each row index in an HTML table

My goal is to dynamically change the colors of selected rows every time a button outside the table is clicked. I am currently utilizing the latest version of Angular. While I am familiar with setting row colors using CSS, I am uncertain about how to manip ...

Tips for emptying the search field in primeng multiselect widget

Is it possible to reset the search input field in primeng multiselect? I've been referring to the tutorial on primeng multiselect provided in the following article. https://www.primefaces.org/primeng/showcase/#/multiselect https://i.stack.imgur.com ...

Unit testing in Typescript often involves the practice of mocking

One challenge with mocking in Typescript arises when dealing with complex objects, as is the case with any strongly-typed language. Sometimes additional elements need to be mocked just to ensure code compilation, such as using AutoFixture in C#. In contras ...

The TypeScript datatype 'string | null' cannot be assigned to the datatype 'string'

Within this excerpt, I've encountered the following error: Type 'string | null' cannot be assigned to type 'string'. Type 'null' cannot be assigned to type 'string'. TS2322 async function FetchSpecificCoinBy ...

Encountered an issue while resolving dependency tree for angular tslib

When running npm install, I encountered the error shown in this image: https://i.stack.imgur.com/PInQE.png The CLI version is Angular CLI: 9.1.8. Any assistance would be greatly appreciated. Thank you! ...

Dynamically set the value of a form in <mat-select> using binding

In my 'div' element, I have implemented a "mat-select" feature that contains a dropdown of country lists in a multi-select format. I am looking to automate the process of populating the countries within the "mat-select" when a button is clicked. ...

Maintaining scroll position in React Router v6

My website's homepage displays a user's feed. When a user clicks on one of the feed cards, they are taken to a different URL. However, when the user returns to the homepage, it automatically scrolls to the top. I am looking for a way to preserve ...

Guide to Angular Interface Styling - Ambiguous Suggestions

After reviewing the Angular style guide for interfaces, I find two recommendations particularly perplexing: The suggestion to use a class instead of an interface for services and declarables (components, directives, and pipes) leaves me puzzled. Similarl ...

Two components are loaded simultaneously by Angular

I encountered a strange bug in my Angular2 frontend application. After logging in, I see two components appearing simultaneously - the login component and the main component. In the screenshot above, the login functionality inputs should not be visible. ...