10

I am working with Angular2 and want an element to conditionally display based upon the result of a function call.

When I do this I've noticed that the function is called multiple times.

@Component({
  selector: 'my-app',
  template: `
    <h1>Hello</h1>
    <div *ngIf="returnsTrue()">
       <h1>World</h1>
    </div>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = 'Angular2'
  }

    returnsTrue(): boolean {
        console.log('Returning true');
        return true;
    }
}

See associated plnkr:

http://plnkr.co/edit/MScwD3LaIj9YfBlwWltw?p=preview

The 'Returning true' console.log is output 4 times.

Can anyone point me as to why this occurs?

And is there anyway to avoid it?

I've seen the following post however with it being related to Angular 1 and the digest cycle being re-written for Angular2 I'm not sure it's relevant:

ng-if being called more times than it should

Community
  • 1
  • 1
SamF
  • 255
  • 1
  • 3
  • 16

1 Answers1

11

I suspect that your function is called on every change detection cycle, particularly in dev mode when Angular is checking the expression in the *ngIf for changes multiple times, and in doing so is calling the function.

One way to avoid it would be to change a class variable in your function, and monitor that variable in your *ngIf:

@Component({
  selector: 'my-app',
  template: `
    <h1>Hello</h1>
    <div *ngIf="isTrue">
       <h1>World</h1>
    </div>
  `,
})
export class App {
  name:string;
  isTrue:boolean = false;
  constructor() {
    this.name = 'Angular2'

    setTimeout(() => {
      this.returnsTrue();
    }, 5000);

  }

    returnsTrue(): boolean {
        console.log('Returning true');
        this.isTrue = true;
    }
}

I adapted your Plunker to show this.

Harry
  • 3,312
  • 4
  • 34
  • 39
  • This answer worked for me once I moved the function (this.returnsTrue(); in the anser) call to ngOnChanges(). Leaving it in ngOnInit() only called the function once rather than once per component update. – wdspider Sep 08 '17 at 15:41