angularlabelangular-directivetwo-way-bindingone-time-binding

One time binding directive not working with Angular 4


I'm trying to implement a directive to implement the one time binding so when I use this directive I want to use the one time binding.

I made this example; https://stackblitz.com/edit/angular-bhayzy

In my HTML I have:

<div>
  message: {{labels.message('hello')}}
</div>

<div *oneTime>
  message one-time: {{labels.message('secondHello')}}
</div>

Labels is a class with message function:

  public static message(field): string {
    console.log('called: ', field);
    return this.MYCLASS.LABELS[field] || 'no message';
  };

Starting the application I get 6 console with the message, 3 for 'hello' but also 3 for 'secondHello' but in this HTML element I have the *oneTime.

Debugging OneTimeDirective it seems I never enter in the directive...


Solution

  • You're detaching ChangeDetectorRef after VM turn because it's inside setTimeout.

    setTimeout(() => view.detach());
    

    So Angular performs all change detection cycles that happens during bootstrapping your application and it runs 3 times.

    Read why it happens so many times here:

    But if you remove setTimeout then your template won't be rendered at all.

    *oneTime directive prevents you from the upcoming change detection cycles that will happen after any DOM event or async calls.

    As it was correctly noticed you can custom pure pipe to improve performance for your part of code.