1

What is the defined lifecycle of property binding in Angular 2? For example I have following element in my template:

<input type="radio" name="{{choice.question_id}}" value="{{choice.id}}"
                    [checked]="isSelected()"
                    (change)="select()"
                    required>

When are exactly those properties and event callbacks bound? As far as I know, there is some cycle which automatically refresh the bindings. Where I can find better explanation about that cycle?

My goal above is to make radiobutton selected by default if isSelected(). Thus polling the isSelected() after initial rendering is redundant and inefficient. How can I restrict that [checked]="isSelected() just to moment when element is first added to DOM?

Tuomas Toivonen
  • 21,690
  • 47
  • 129
  • 225

1 Answers1

2

Bindings are evaluated at every change detection cycle.

Change detection is run after some async execution happened. Angulars zone patches most async APIs like addEventHandler, removeEventHandler, setTimeout, ... After such events are processed Angular runs change detection and checks all expressions bound to inputs ([], {{}}).

Such events happen very frequently and thus bound expressions are evaluated very frequently. Therefore it's important to make these expressions efficient. This is one of the reasons the Angular team discourages binding to functions and to rather assign the result to a property and bind to that property instead because compairsion of properties is quite efficient, or even better, bind to observables and promises (using the | async pipe) that actively notify about changes.

You can't define at what point a binding is evaluated. It is evaluated every time change detection runs. You can control though when change detection runs on your component or its child components by setting ChangeDetectionStrategy.OnPush instead of ChangeDetectionStrategy.CheckAlways (default) and invoke change detection "manually".

In devMode default, change detection also aways runs twice to check if the first change detection turn itself didn't cause any changes in the model which is considered a bug. This needs to be taken into account if you're wondering why a bound method is called so frequently. If in devMode divide the count by 2 to get the effective number as it would happen in prodMode.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • So would one option to be bind [checked] to private field, which is initialized by ngOnInit() { checked = service.isChecked() } to reduce the service call load. The question is, if ngOnInit is called every time when component is added to DOM by structural directives or routing. Logic in my application is that service maintains the state of "form" and when user navigates away and back to a certain part of form, each input polls it's state from the service. So service call is only needed when something is rendered once – Tuomas Toivonen Jun 05 '16 at 12:48
  • Yes `ngOnInit()` is called every time when the component is added to the DOM by structural directives or routing. I wouldn't worry about calls to the service (at least if this doesn't cause some server request or DOM updates for every call) causing to much processing power. Components aren't added/removed too often and the cost for a call to a service is neglectable compared to the cost that adding a component to the DOM causes. I'd consider this premature optimization. If the service does expensive work for every call than try to optimize that instead by for example caching results. – Günter Zöchbauer Jun 05 '16 at 13:32
  • See also http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2-http-network-call-in – Günter Zöchbauer Jun 05 '16 at 13:32