Angular 2+ one-time binding

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.

Some info here:

  • http://www.syntaxsuccess.com/viewarticle/change-detection-in-angular-2.0

  • https://angular.io/docs/ts/latest/api/core/index/ChangeDetectionStrategy-enum.html


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>