0

I have the following async method. I use a loader in order to update the user interface, visibility of which is based on the isExporting flag.

public async copyToClipboard(element: HTMLDivElement): Promise<void> {

  this.isExporting = true; // <<<<<<<<<<<<<<<<<<<<<< HERE

  const data = await html2canvas(element, { scale: 1.5 }).then((canvas) => {
    canvas.toBlob((blob) => {
      const item = new ClipboardItem({ 'image/png': blob! });
      navigator.clipboard.write([item]).then((res) => {

        this.isExporting = false; // <<<<<<<<<<<<<<<<<<<<<< HERE

        this.notyfService.instance.success({
          message: this.translateService.instant('message.export.success'),
          duration: 2000
        });
      });
    });
  });
}

Then I have

<button [disabled]="isExporting" (click)="copyToClipboard(container!)">
    <kendo-loader *ngIf="isExporting"> </kendo-loader>
</button>

Even if isExporting is set to false before the NotifyService message, I get first of all the service message popup after the clipboard is updated, and only several seconds after the message the loader disappears - isExporting is updated in the main 'thread'.

Is there a way to notify the main 'thread' that isExporting is updated immediately?

serge
  • 13,940
  • 35
  • 121
  • 205
  • 1
    Have you tried using `ChangeDetectorRef.detectChanges()`? –  May 16 '22 at 13:46
  • @MikeS. how should we use it? – serge May 16 '22 at 13:48
  • There's lots of [documentation](https://angular.io/api/core/ChangeDetectorRef) on that topic ;) In short, you inject it into your class just like services and call `.detectChanges()` from whereever you update template bound variables. –  May 16 '22 at 13:54
  • @MikeS. after your suggestion I have a lot of workaround (see my answer bellow). However, now only second update is OK (to False), not the first (to True) – serge May 16 '22 at 14:32
  • I'm not sure why it wouldn't update on `this.isExporting = true;`, you'd need to show me a reproducer because from the code you provided, everything should be working. –  May 16 '22 at 21:34

1 Answers1

0

Following the Mike S. suggestion, I have updated the component like this:

constructor(
  private notyfService: NotyfService,
  private cd: ChangeDetectorRef,
) {
}


public async copyToClipboard(element: HTMLDivElement): Promise<void> {

  this.isExporting = true;
  this.cd.detectChanges();

  const data = await html2canvas(element).then((canvas) => {
    canvas.toBlob((blob) => {
      const item = new ClipboardItem({ 'image/png': blob! });
      navigator.clipboard.write([item]).then((res) => {
        this.notyfService.instance.success({
          message: 'message.export.success',
          duration: 2000
        });

        this.isExporting = false;
        this.cd.detectChanges();
      });
    });
  });
}

Now the loader is updated OK after the treatment, however I still have a delay of 3 seconds before it starts to spin, probably because isExporting=true is not detected immediately, even if I use detectChanges.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
serge
  • 13,940
  • 35
  • 121
  • 205