2

why every time i use a ngFor, the loops runs 4 times? and how to stop it? can someone explain to me what is happening?

here is a little sample.

1
  • where is a bug? you have an array with 4 objects Commented Oct 16, 2019 at 17:03

3 Answers 3

2

The reason that the iShouldrepeatOneTime method is called 4 times is because of Angular's default ChangeDetectionStrategy. By default, every time there is a change in your component, in this case for every loop, Angular will check your whole component for changes. The only way for Angular to know whether the return value of iShouldrepeatOneTime has changed is by calling it.

So how do you get around this? There are two choices that come to mind:

  1. Use OnPush ChangeDetectionStrategy, or
  2. Ensure that you do not bind to methods in your template for reasons other than event emitters. Bind to properties instead.

I will expand on my second point. Imagine you had a property in your component someValue and a method calculateSomeValue() as follows:

someValue = 'foo';

calculateSomeValue(): string {
  return 'bar';
}

In your template, having {{ someValue }} is more efficient than {{ calculateSomeValue() }} because in the former approach Angular already knows if the value of the property has changed and if it needs to be updated in the view. In the latter approach, Angular needs to call the method first before it knows if it needs to update the value in the view.

Sign up to request clarification or add additional context in comments.

Comments

1

There are no bugs here! You have 4 outputs because your array has 4 objects. If you want to iterate values by specific field, you can add pipe:

1) add this pipe to the end of your app.component

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "mymap"
})
export class ArrayMapPipe  implements PipeTransform {
  transform(array: any, field: string): any[] {
    if (!Array.isArray(array)) {
      return;
    }
    return array.filter((e: any) => e.camp2 === field);
  }
}

2) import the pipe to the app.module

import { AppComponent, ArrayMapPipe } from './app.component';
...
declarations: [ AppComponent, HelloComponent, ArrayMapPipe ]

3) you can use it like this:

<div *ngFor="let key of array | mymap:'orange'">
    <div>
        <span class="teste">{{key | json}} </span>
    </div>
</div>

Comments

0

That is not a Bug. It is not good practise using function calls in value bindings. In such case function will be called every time when Angular runs change detection. You should do it as follows.

<div>{{ someValue }}</div>


export class AppComponent {

  someValue;

  ngOnInit() {
    this.someValue = this.someMethod();
  }

  someMethod(){
    const someValue = 2;
    return someValue;
  }
}

Read more about Angular DOM update mechanism.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.