Search code examples
angularangular2-template

Why does this method/gettor get called X times in an Angular 2 service


I am trying to bind a value in my HTML component to a property in a service. If the private variable is null then it needs to go off and get the value from an HTTP call.

However, I noticed that as soon as I bind to the property getter in my HTML component then it fires multiple times.

I have simplified the example with: this Plunker

  get Item(): string {
      console.log("Item()", this._item);
      return this._item;
  }

Open the Console and observe the multiple outputs of "Item() Initiated". I would expect it to only be hit once. (the result is the same with a method instead of a getter). If I use the getter in a click method it only fires once.


Solution

  • This is because the value bound on the html has to be evaluated every time something "has changed" in the app so that if the value of the bound item has changed it will be reflected to the html, thus giving you this magical autoupdating binding. This is probably what you want in 90% of the cases, as you don't want to worry about notifying angular to update a value of a bound property.

    That being said if you have some heavy logic in the getter, or you prefer to control when the value will be updated you can change the components changeDetectionStrategy to onPush like in this plunker.

    @Component({
      selector: 'my-app',
      template: `
        <div><button (click)="_service.ShowItem()">Show Item</button></div>
        <div>{{_service.Item}}</div>
      `,
      providers: [ Service ],
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    

    There is an excellent explanation of how angular2 change detection works by thoughtram

    This is like saying, "do not check this component when doing change detection, I will let you know when to check it".

    You then can use a service called ChangeDetectorRef to mark the component for change detection.

    For http what you want to do is have a trigger to do the http call and then get the value you need from the response and "cache" it somewhere so that you can bind it to the UI. The trigger can be a variety of things depending on your case, eg. interval, recursion, button etc