run a function once ngFor has completed rendering the data

I'm attempting to run a function every time my ngFor finishes loading data from the API.

However, the callback only works on the initial load of the ngFor.

How can I make sure that the callback is executed whenever my ngFor data changes?

I found a solution here:

Here's what I have so far...

HTML

<button class="btn" (click)="changeDate()"></button>

<div *ngFor="item of items; let last = last">
    <div>{{item}}{{last ? ngForAfterInit() : ''}}</div>
</div>

TS

this.ngForIsFinished = true;

ngForAfterInit() {
    if (this.ngForIsFinished) {
        this.ngForIsFinished = false;
    }
}

changeDate() {
    // trigger ngFor content change here
}

The answer suggests setting ngForIsFinished back to true, but I'm struggling to figure out where in my code to do that.

Answer №1

Consider utilizing the ChangeDetectionStrategy.OnPush and the last variable in your ngFor loop. This is recommended because with ChangeDetectionStrategy.Default, methods are always checked, leading to multiple calls of fooMethod(...):

<div *ngFor = "let title of iterated; let i=index; let last=last">
  {{last ? fooMethod(last) : '' }}  
</div>

In your component file:

import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent  {
  name = 'Angular 4';

  iteratedData = [
      {"title":"test1","description":"foo","name":"name1"}, 
      {"title":"test2","description":"foo","name":"name2"}, 
      {"title":"test3","description":"foo","name":"name3"}, 
      {"title":"test4","description":"foo","name":"name4"}
  ];

  fooMethod(v) {
    if (v)
      console.log(`This is from the method ${v}`);
  }
}

UPDATE:

After loading data, it's advisable to call the slice method as Angular 2 change detection strategy doesn't monitor array or object contents. Therefore, creating a copy of the array after mutation is suggested:

this.iteratedData.push(newItem);
this.iteratedData = this.iteratedData.slice();

Alternatively:

constructor(private changeDetectorRef: ChangeDetectorRef)

You can then invoke the markForCheck method to trigger a changeDetection:

this.iteratedData.push(newItem);
this.changeDetectorRef.markForCheck();

Answer №2

Check out this demonstration:

Component:

    import { Component } from '@angular/core';

        @Component({
          selector: 'my-app',
          templateUrl: './app.component.html',
          styleUrls: [ './app.component.css' ]
        })
        export class AppComponent  {
          name = 'Angular 5';
          data:any = [];

          ngAfterViewInit(){
            this.updateData();

          }

          updateListAfterForLoop(item) {
            alert('FOR LOOP COMPLETED : '+ item);
           }


           UpdateData(){
              let i = 0;
              setInterval(()=>{
                this.data=[];
                for(var j=0; j<10; j++){
                 this.data.push("TEST DATA "+ j+" SET AT :  "+i);
               };
               i+=1;
            },7000);
          }
       }

html:

<div *ngFor="let item of data; let last=last;">
{{item}} {{last? updateListAfterForLoop(item) :''}}
</div>

The SetInterval acts as an API to populate the data. This implementation has been successful for me.

https://stackblitz.com/edit/pokemon-app-4n2shk

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

Retrieving dates from a database and populating them into a jQuery UI Picker using PHP

I need to retrieve dates from the database using PHP and highlight them in a datepicker. Here is how I am attempting to accomplish this: HTML Date: <input type="text" id="datepicker"> // Static dates // An array of dates var eve ...

Organizing DIVs upon website initialization

My website features a layout with three columns: <div id="column1"></div> <div id="column2"></div> <div id="column3"></div> I currently have 3 divs on the webpage: <div id="1">aaa</div> <div id="2">b ...

How can I use Angular2 to ensure that a child component automatically updates when there is a change in the parent's property?

After reviewing the components provided below, it appears that the parent's property updates correctly, but unfortunately, the changes are not reflected in the child component. What steps should I take to ensure that the child component accurately ref ...

Guide on transferring information obtained from a service to an Angular datatable

Recently, I started working on Angular 4 and encountered an issue while trying to display data from an Angular service in JSON format using angular-datatable. Despite trying various options, I am unable to get the data to display within the columns of the ...

To convert an image file into a string, use JSON.stringify before including it in an AJAX request

Is it possible to send image files contained within JSON objects in an array via an AJAX call using JSON.stringify? When attempting to send the data through an AJAX call, and utilizing JSON.stringify with an array containing JSON objects that have image f ...

The Design and Layout of a MEAN Stack Application

When creating a MEAN Stack app using the express-generator npm, everything worked perfectly but I found myself confused about the purpose of certain files. For instance: The package.json included this code snippet: "script":{"start": "node ./bin/www"} ...

Retrieve the attribute values of an element in Angular after utilizing a template

As a newcomer to Angular, I am exploring the use of custom directives for the first time. Currently, I have a table where each cell contains a data attribute such as "data-dept="service". Before applying a directive to overwrite this value, I would like to ...

Strategies for dynamically altering Vue component props using JavaScript

for instance: <body> <div id="app"> <ro-weview id="wv" src="http://google.com"></ro-weview> </div> <script> (function () { Vue.component("ro-webview", { props: ["src"], template: ` <input type="t ...

When `focus` is bound to a jQuery event handler, the behavior of the select element becomes erratic on

What causes the odd behavior where users need to click twice on a select-option for it to drop down/up after binding an eventhandler to the focus event using jQuery? $('input, select, textarea').focus(function() { $(this).addClass('input_ ...

Patiently waiting for the component variable to be assigned through subscription

I am facing an issue with two calls in my component. The second call depends on the result from the first call. In the first call, I set the value for my component variable "locked". The second call should only be executed when the result is true, meaning ...

What is the best way to eliminate an object from an array of objects that fulfills a specific condition?

Upon receiving an object in my function containing the information below: { "name": "Grand modèle", "description": "Par 10", "price": 0, "functional_id": "grand_modele_par_10", "quantity": 2, "amount": 0 } I must scan the next array of objec ...

What is the best way to align the 'Typography' component in the center?

Attempting to center it using flexbox with justify-content did not yield the desired result. I also tried replacing the Typography component with a div tag, but still no success. import {AppBar,Zoom,Toolbar,Typography,CssBaseline,useScrollTrigger,Fab,ma ...

Creating columns on the fly within a row

I would like to create a layout where images are displayed in one row, but if the screen size changes, I don't want them to wrap and display below. Instead, I want to show a button that redirects to another page. I'm not sure how to achieve this. ...

Looking for a way to assign the object value to ng-model within a select tag from an array of objects? Also, curious about how to easily implement filters on ng-options?

Here is the HTML code for creating a question template: <body ng-controller="myCtrl"> {{loadDataSubject('${subjectList}')}} {{loadDataTopic('${topicList}')}} <h1 class = "bg-success" style="color: red;text-align: ...

Component with a dynamic CSS file implementation

I am looking to empower users of my app with the option to select a theme. To achieve this, I have created multiple SCSS stylesheets that offer variations in design elements. However, I am faced with the challenge of loading the appropriate stylesheet base ...

Navigating to a specific section upon clicking

Imagine a scenario where there is a landing page with a button. When the button is clicked, redirection to another page with multiple components occurs. Each component on this new page serves a different function. Additionally, the desired functionality in ...

Ways to authenticate custom kinds in JSON schema?

When working with JSON Schema, one of the challenges I have faced is the limitation on supporting ‘double’ and ‘float’ types for numeric values. While using AJV in JavaScript to validate a schema, it fails due to this restriction. Is there a way to ...

Helping individuals identify the HTML5 Geolocation notification

Currently working on a website that requires users to accept the browser prompt for location sharing. Many users seem to overlook this prompt, which can lead to issues. The main problem we are facing is that each browser displays this prompt differently: ...

Accessing nested objects within a JavaScript array for an Express API

My current data sample looks like this: var data = [{ articles : [{ id : '0', url : 'foo', title : 'Foo', body : 'some foo bar', category : 'foo', tags : ...

Can you share the outcomes of executing a Node.js program in real-time?

Is there a method to execute a program (such as tcpdump) and have nodejs capture the console output in real-time to display in an HTML format without saving it? I am interested in running a program that displays information in the console, with the capabi ...