1

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...

yurzui
  • 171,085
  • 24
  • 365
  • 354
Hazlo8
  • 565
  • 8
  • 27
  • You should really just consider creating a [custom pipe](https://angular.io/guide/pipes#custom-pipes). It will effectively cache the results to avoid unnecessary calls/executions and is vastly more straightforward than that `oneTime` directive. – Alexander Staroselsky Feb 26 '19 at 16:41
  • Hi, thanks but I have the same problem with the pipe, I have 4 console: https://stackblitz.com/edit/angular-djwvh2 – Hazlo8 Feb 26 '19 at 17:46
  • 1
    You would want to remove `pure: false` from that example. – Alexander Staroselsky Feb 26 '19 at 18:05

1 Answers1

0

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.

yurzui
  • 171,085
  • 24
  • 365
  • 354