angular 2 one time binding


In angular 1 we could do one time binding in this way: {{ ::myFunction() }}.

In angular 2 this is throwing:

EXCEPTION: Template parse errors:
Parser Error: Unexpected token : at column 2 in [{{ ::consent(false, undefined, box) }}] in [email protected]:29 ("ull-right" href="" (click)="consent(true, $event, box)">De acuerdo</a>
        <span class="hidden">[ERROR ->]{{ ::consent(false, undefined, box) }}</span>

How can we do one time binding in angular2?

ChangeDetectionStrategy.CheckOnce is the solution for this problem.

Some info here:


I found solution for one time binding in angular 2 here: https://github.com/angular/angular/issues/14033

I created this directive:

 import { Directive, TemplateRef, ViewContainerRef, NgZone } from "@angular/core";

@Directive({
    selector: '[oneTime]',
})
export class OneTimeDirective {
    constructor(template: TemplateRef<any>, container: ViewContainerRef, zone: NgZone) {
        zone.runOutsideAngular(() => {
            const view = container.createEmbeddedView(template);
            setTimeout(() => view.detach());
        })
    }
}

And used it:

  <some-selector *oneTime [somePropertyToOneTimeBinding]="someValueToOneTimeBinding"></some-selector>

For example:

     <iframe *oneTime [src]="myUrl"></iframe>

Currently, you cannot do one time binding with Angular 2. However, you can know when your binding changes and reset your inputs.

Angular 2 provides OnChanges lifecycle hook for the same. You need to implement OnChanges interface to get the changes.

See the code example below where, I am storing the data-bound property in a private variable when OnInit is called.

export class Footer implements OnInit, OnChanges {
  @Input() public name: string;
  private privname: string;

  constructor() { }

  ngOnInit() {
    this.privname = this.name;
  }


  ngOnChanges(changes: { [key: string]: SimpleChange }): void {
    if (!changes["name"].isFirstChange()) {
        this.name = this.privname;
    }
  }
}

Later when other changes occur, I am setting the value to its old value on subsequent changes.

This mechanism works like One-time binding.

Alternate solutions: You could also use a setter function to capture the changes.


ChangeDetectionStrategy.CheckOnce is the solution for this problem.

This has been updated to OnPush see also comment in code:

export declare enum ChangeDetectionStrategy {
    /**
     * `OnPush` means that the change detector's mode will be set to `CheckOnce` during hydration.
     */
    OnPush = 0,
    /**
     * `Default` means that the change detector's mode will be set to `CheckAlways` during hydration.
     */
    Default = 1,
}

Since one time read/bind isnt possible by default in angular, I think writing a public getter function will solve the issue.

For example

public getValue():number {
 return mynumber ? mynumber : 25; // if mynumber is not undefined the mynumber else return 25
}

//In html template
<input type="range" min="getValue()" max="100">

This will work perfectly if the getter function is able to reply back before the template rendering takes place. So the initialization of mynumber would be great if done in ngOnInit() function