Utilizing a function in an infinite loop within *ngFor along with an asynchronous pipe for an HTTP call

Using a function in an *ngFor statement:

@Component({
  selector: 'foo-view',
  template: '<div *ngFor="let foo of loadAll() | async"></div>'
})
export class FooComponent {

  loadAll(): Observable<Foo[]> {
    return this.http.get(`api/foos`)
      .map(response => response.json() as Foo[]);
  }

}

Upon running the code, it continuously sends HTTP requests in an infinite loop. Why is this happening and how can I prevent it?

P.S. I am aware of the standard workaround like

@Component({
  selector: 'foo-view',
  template: '<div *ngFor="let foo of foos"></div>'
})
export class FooComponent implements OnInit {

  foos: Foo[] = [];

  ngOnInit() {
    this.loadAll().subscribe(foos => this.foos = foos);
  }

  loadAll(): Observable<Foo[]> {
    return this.http.get(`api/foos`)
      .map(response => response.json() as Foo[]);
  }

}

However, I am searching for a way to eliminate the extra variable.

Answer №1

To clarify, the situation is not an endless loop. Angular runs the change detector to determine if any bindings have been updated, triggering the loadAll() method and making an HTTP call. This process is necessary because Angular cannot assume that nothing has changed since the last check. Obviously, this constant rechecking is undesirable. The frequency of these checks may also be influenced by other components, such as its parent.

A solution to prevent this issue is creating a property like foos: Foo[], as demonstrated in your example.

If you prefer not to introduce another state variable, you could establish an Observable chain that replays cached data:

private cached;

ngOnInit() { 
  this.cached = this.http.get(`api/foos`)
    .map(response => response.json() as Foo[])
    .publishReplay(1)
    .refCount()
    .take(1);
}

In your template, you can then simply use:

<div *ngFor="let foo of cached | async"></div>

With this implementation, only one initial request will be made, and subsequent subscribers will receive the cached value without additional requests.

Furthermore, with RxJS 5.4.0 or later versions, you can utilize shareReplay(1) as a more convenient alternative to .publishReplay(1).refCount().

Additionally, you have the option to adjust the Change Detection Strategy of the component using the changeDetection property to manually trigger the change detection process. Refer to ChangeDetectionStrategy for more information.

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

Encountered an npm error while attempting to start an Angular project

When attempting to run my project using ng serve -o, a warning message popped up on the screen stating: Your global Angular CLI version (15.2.2) is higher than your local version (15.0.4). The local Angular CLI version will be used. To disable this warnin ...

Create an onClick function that can direct you to a specific hyperlink without triggering a new browser window to open

Material UI is being used and a home icon has been imported into the navbar as shown below <Home edge="start" color="inherit" aria-label="home" onClick={event => window.location.href='/ <Home fontSize="lar ...

What is the significance of an empty href attribute in the HTML <base> tag?

If my website URL is: http://example.com/path/to/dir/index.html And I decide to proxy this page through: http://proxyserver.com/path/to/dir/index.html. I would like all relative URLs on the page to be resolved by proxyserver.com instead of example.com. Wh ...

What's the best way to provide route access to the same menu for two distinct user roles using AuthGuard within Angular?

I developed an application that includes three different user roles: ROLE_USER, ROLE_MODERATOR, and ROLE_ADMIN as shown below: export enum Role { User = 'ROLE_USER', Moderator = 'ROLE_MODERATOR', Admin = 'ROLE_ADMIN&apo ...

Issue when utilizing TypeScript MongoDB Definitions (Unable to locate namespace)

I am currently working on implementing MongoDB typings that I installed using the following command: npm install @types/mongodb -D Now, I want to utilize these types within a function like this: export default async function insertOne(collection:any, da ...

Encountered a problem while trying to install angular-cli on a Windows 10

While attempting to set up angular-cli on my Windows 10 device, I used npm install -g @angular/cli. However, an error popped up as follows: C:\Users\kumar>npm install -g @angular/cli npm ERR! Unexpected end of JSON input while parsing near &a ...

Tips for utilizing ion-img within an Ionic 3 application?

I am currently developing an app using Ionic 3 that includes a large number of images spread across different pages. Initially, I used the default HTML image tag to display these images. However, this approach caused lag in the app's performance and a ...

The argument of type 'NextRouter' cannot be assigned to the parameter of type 'Props' in this scenario

In my component, I am initializing a Formik form by calling a function and passing the next/router object. This is how it looks: export default function Reset() { const router = useRouter(); const formik = useFormik(RecoverForm(router)); return ( ...

Verify role declarations and display components if valid

I am currently developing an application using Angular on the front-end and ASP.NET on the back-end. Within this application, there are two roles: user and admin. I have implemented a navigation bar with several buttons that I need to hide based on the use ...

Error message: An unhandled TypeError occurs when attempting to access properties of an undefined object (specifically, the 'then' property) while refreshing the token using axios

Is there a way to refresh tokens in axios without interrupting the flow? For example, when the server returns an access token expiration error, I want to queue the request and replay it after getting a new token. In React, I'm using promises as shown ...

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 ...

The Node Express proxy is returning a 404 Not Found status code instead of the expected 200 success code

Here is the content of my server.js file: const express = require('express'); const http = require('http'); const path = require('path'); //const request = require('request'); const app = express(); var cors = requi ...

Ways to retrieve a value from outside the Angular subscribe block

Custom Template <div class="row" *ngFor="let otc of this.jsonData;index as j"> <div> <table class="table table-striped table-fixed"> <tr *ngFor="let opc of this.winServiceInfo ...

Is there a way to dynamically transfer projected content to child components without using <ng-content> for rendering?

Let's say I have a <hook> component that dynamically creates a child, how can I transfer the content (which Angular would usually render inside a <ng-content></ng-content> in the hook's template) as ng-content to that child comp ...

JavaScript now has Type Inference assistance

When attempting to utilize the Compiler API for processing JavaScript code and implementing Type inference to predict types of 'object' in a 'object.property' PropertyAccessExpression node, I encountered some issues. Some simple example ...

Is there a way to load an image onto the ngx-image-cropper without triggering the imageChangedEvent event?

My latest project involved creating a custom cropper using ngx-image-cropper, which allows for cropping and rotating images. For the sprint demo, I needed the images to be displayed as soon as the application loads without having to trigger the fileChangeE ...

Sortable layouts and tables in Ionic 3

I found a great example of an Ionic table that I'm using as reference: https://codepen.io/anon/pen/pjzKMZ <ion-content> <div class="row header"> <div class="col">Utility Company Name</div> <div c ...

How can I access Angular in the console through devtools on Angular 8?

I'm currently using Angular 8 and I came across this outdated advice on how to test an AngularJS service from the console on Stack Overflow. Despite following the steps mentioned, I encountered some disappointing output. Angular is running in the dev ...

Unable to create property within array in model

I am facing an issue while trying to access the name property of an array called Model[] generated from my Model.ts file. When attempting to use it in my app.component, I receive an error stating that the property 'name' does not exist on type Mo ...

Unable to initiate a new project in Node.js

As I was working on adding a new project in Angular, everything was running smoothly until today. However, when trying to create a new project today, I noticed that the node_modules folder is missing and encountered the following errors: https://i.stack.i ...