Using the Async Pipe within a template inside an ngFor directive causes a series of HTTP GET requests to

Below is a component Template I am working with:

<div *ngFor="let ctrl of data; trackBy:ctrl?.Id">
   <div *ngIf="getNext(ctrl.nextDate) | async as next">
        <span>{{next | date: 'dd.MM.yyyy'}}</span>
   </div>
</div>

In this template, there is a method called getNext() that returns an Observable<Date>:

public getNext(deadline: string): Observable<Date> {
   return this.http.get<Date>(`${this.config.apiEndpoint}/api/meeting?deadline=${deadline}`);
}

My issue arises when I try to invoke the method and subscribe to the observable using the async pipe in the template. The problem is that when I run the application, it keeps generating endless GET and OPTIONS requests.

Even if I move the method call outside the ngFor loop, the same issue occurs. The call needs to be made inside the ngFor loop because the parameter varies for each collection item.

I'm puzzled as to why the method is only being called once and no additional calls are generated after the initial subscription?

Answer №1

It is often discouraged to call functions in a template as it can result in unpredictable outcomes. To avoid this, consider restructuring your code like this:

data: any = [....] // some data
data$: Observable[];

ngOnInit() {
    this.data$ = this.data.map(elem => this.getNext(elem));
} 

public getNext(deadline: string): Observable<Date> {
   return this.http.get<Date>(`${this.config.apiEndpoint}/api/meeting?deadline=${deadline}`);
}

You can then display the data in your template like this:

<div *ngFor="let ctrl of data$">
   <div *ngIf="ctrl | async as next">
        <span>{{next | date: 'dd.MM.yyyy'}}</span>
   </div>
</div>

Feel free to check out this stackblitz example demonstrating a similar process: https://stackblitz.com/edit/angular-nyn4qz

Answer №2

During each event cycle, Angular executes the getNext function which sends a new http request and generates a new Observable. To optimize performance, it is advisable to cache the initial Observable created by the function call. I suggest creating them in the controller and passing them as variables in the template.

Answer №3

It is highly likely that your issue stems from change detection.

Whenever Angular detects a potential change in what is required to render your template (such as during any browser event unless your component is set to OnPush), it will redraw the component, subsequently reinitiating the loop and observable.

In such scenarios, you have two options:

  • Ensure that change detection is only triggered when necessary (e.g., by aligning your component with the OnPush ChangeDetectionStrategy). This method usually works best if only a limited number of @Input() properties prompt updates.
  • Make the requests just once in ngOnInit or ngOnChanges (if data is an @Input() of your component), store the results in an array, and use this array in your template for iterating through data (this approach is recommended).

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

Updating content in Angular 4 X-editable form does not reflect changes in form value

Having trouble with the jQuery X-editable library in an Angular 4 environment. Here's the code snippet: model.html <a href="javascript:;" onClick="event.stopPropagation(); event.preventDefault();" editableToggle="#editable{{selectedModel.id}}"> ...

What is the best way to add all the items from an array to a div element?

I am currently facing an issue where only the last object in my array is being added to my div using the code below. How can I modify it to add all objects from the array to my div? ajaxHelper.processRequest((response: Array<Vehicle.Vehicle>) ...

Obtaining the complete HTTP response status within an Angular 6/7 service

Within my Angular 7 service, I have the following code: import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { map } from 'rxjs/operators'; import { BehaviorSubjec ...

"Removing the index from an object's type in TypeScript: A step-by-step guide

When using [key: string], my type will accept any key. However, I am attempting to avoid this because in certain situations, I am redefining types for properties. Take the following scenario into consideration: interface IObject { [K: string]: number ...

Resolving undefined in Ionic 4: Returning Data from Modal

I'm attempting to create a modal window that utilizes a radio group. When a user selects a value from the radio group, I want the modal to return the selected object. Here is the code for the radio group page and HTML: export class PopoverstationsPa ...

The `ngx-infinite-scroll` feature does not function properly on mobile devices when used in conjunction with the

I'm currently working on an Angular project that utilizes the mat-sidenav layout and routing. I came across an issue when trying to display a list of elements from a database using ngx-infinite-scroll. Following the user guide for ngx-infinite-scroll, ...

"Encountering a Bug in Angular 2 Related to Chart.js

I am currently in the process of developing a Twitter-style application using a Typescript/Angular2 front-end framework and a Node.js back-end. The foundation of my project is derived from Levi Botelho's Angular 2 Projects video tutorial, although I h ...

Creating dynamic HTML content for printing tasks with the use of variables in Angular6

After running this code, I noticed that instead of values, I am receiving the object names. export class PrescriberComponent implements OnInit { constructor() { } people = [ {id: 1, forename: 'John', surname: 'Doe'}, {id: 2, f ...

Bringing in TypeScript declarations for the compiled JavaScript librarybundle

I have a custom library written in TypeScript with multiple files and an index.ts file that handles all the exports. To consolidate the library, I used webpack to compile it into a single index.js file but now I'm facing challenges importing it with ...

having difficulty accessing the value within the Angular constructor

My current issue arises when I click on a button and set a value within the button click method. Despite declaring the variable in the constructor, I am unable to retrieve that value. The code snippet below demonstrates this problem as I keep getting &apos ...

Are you searching for ways to convert an object into an array?

I have a dynamically built object and I need to extract specific fields (the dynamic ones) from it and convert them into an array. In the following code snippet, my goal is to convert towers[X] into an array of objects. {id: "", description: "Teste", tow ...

Guidelines for segregating a Union from an Array

I'm currently utilizing graphql-code-generator to automatically generate TypeScript definitions from my GraphQL queries. I have a specific union within an array that I am trying to extract in TypeScript. Is this feasible? Although I came across an exa ...

Anonymous function's return type

Looking for advice on an anonymous function I've written: static oneOf(options: any[], cb?: Function) ValidatorFn { .... } I'm a TypeScript beginner and unsure how to specify that the 'cb' must return a boolean. Can this be done, an ...

The presence of v-if does not depend on the model value to toggle the element

I have a scenario where I want to hide the dropdown menu for US states if a different country other than the US is selected. The code snippet I am using to achieve this functionality is shown below: <b-row v-for="demo in demographics" :key=&qu ...

No bugs appeared in Next.js

I am currently in the process of migrating a large create-react-app project to NextJS. To do this, I started a new Next project using create-next-app and am transferring all the files over manually. The main part of my page requires client-side rendering f ...

What causes a Typescript error when attempting to escape a newline character?

My approach is quite simple: I concatenate multiple strings and format them to make them more readable. info() { return "x: " + this.xpos.toString() + "\n" \ + "y: " + this.ypos.t ...

Exploring the use of national flag emojis in VS code

I've been attempting to use flag emojis as reactions on a Discord bot, but they just won't cooperate. Every time I try something like this > ':flag_jp:', I encounter the following error: Error: DiscordAPIError: Unknown Emoji EDIT ...

What is the best way to retrieve the initial element in an array?

I am currently using this Rxjs: this.menuSubject$ .pipe(map((items) => items.filter((itm) => itm.active))) .subscribe((res) => console.log(res)); The variable this.menuSubject$ is defined as follows: public menuSubject$ = new Behavi ...

Pinia store encountering a Typescript Vue component issue: error message "The property 'testStore' does not exist on the 'CreateComponentPublicInstance' type."

Within my <script setup> block, I have imported my testStore. However, whenever I attempt to use this.testStore.name in my Vue file, Vetur displays the following error: Property 'testStore' does not exist on type 'CreateComponentPublic ...

Encountering a CSP error during the process of single sign-on using Azure AD with MSAL in an Angular application

I'm currently working on implementing SSO functionality using Azure AD with MSAL in my Angular application. Unfortunately, I've encountered the following error: polyfills.9c9523e6b18dcf83.js:1 Refused to connect to 'https://login.microsofton ...