Angular ngFor lifecycle

1.1k Views Asked by At

I'm using *ngFor to iterate some data like this:

<div *ngFor="let d of [1, 2, 3]"> {{d}} </div>

Everything is fine and I got the result as expected:

<div> 1 </div>
<div> 2 </div>
<div> 3 </div>

Then, I wondered if I use a function instead of {{d}}, so I wrote a function:

protected logAndReturn(item) {
    console.log(item);
    return item;
}

and I used it:

<div *ngFor="let d of [1, 2, 3]"> {{logAndReturn(d)}} </div>

I got the same rendered HTML result as the first code, but console output wasn't my expected output. Console output:

1
2
3
1
2
3

Angular is running in the development mode. Call enableProdMode() to enable the production mode.

1
2
3
1
2
3

The added function was called 12 times now (4 time for each item)

Here is the code that you can test it yourself: jsfiddle

Is my code wrong? Is there any solution to prevent these extra calls? Why did this happen and can anybody explain it a little?

2

There are 2 best solutions below

0
On BEST ANSWER

using methods in the view is the same that using impure pipes. This code will be executed in each event on the view, which can be a lot of times. In our example, the logAndReturn() method only returns a number so it can be assumable to run it in a view but if it would do something more complex, it could be a big problem of performance. with a simple program you can check console.log to see in which step the trace of “logAndReturn” is printed. This is the look of the new component:

export class AppComponent implements 
OnChanges,
OnInit,
DoCheck,
AfterContentInit,
AfterContentChecked,
AfterViewInit,
AfterViewChecked,
OnDestroy
{
  private var01: string = "default value";
  constructor( private trans: TranslatorService ){}
  ngOnChanges (){
     console.log('Trace OnChanges');
  }
  ngOnInit (){
     console.log('Trace onInit');
  }
  ngDoCheck (){
     console.log('Trace doCheck');
  }
  ngAfterContentInit(){
     console.log('Trace After Content Init');
  }
  ngAfterContentChecked(){
     console.log('Trace after contente checked');
  }
  ngAfterViewInit(){
     console.log('Trace after view init');
  }
  ngAfterViewChecked(){
     console.log('Trace after view checked');
  }
  ngOnDestroy(){
     console.log('Trace on destroy');
  }
  testRender() {
    console.log('trace 01');
    return 'This is a test that runs a console log'
  }
  (...)
}

To go deeper in what really is happening here, read the official documentation of Angular 2 about the life cycle

0
On

This issue has no relation with *ngFor, It's the normal behavior of the expression inside the interpolation ({{ }}). It is called by angular intentionally multiple times to check if the expression has changed. Interpolation is meant for fetching (printing) expressions and not recomended for calling methods. It will fire unnecessarily.

Issue is with the method inside interploation not *ngFor