I have a very simple component in Angular 10. When a form is submitted the Blob
of an canvas
-element is created and stored.
Therefor the releveant part of the onSubmit()
function looks like this:
onSubmit(): void {
const canvas: HTMLCanvasElement = getCanvas();
canvas.toBlob((blob: Blob) => {
this.service.create(blob).pipe(first()).subscribe((response: boolean) => {
this.isSuccessful = response;
});
}, 'image/png', 1);
}
The problem is, that isSuccessful
is changed, but these changes are not reflected in the
template.
So what I did is to manually trigger change detection, using a ChangeDetectorRef
:
onSubmit(): void {
const canvas: HTMLCanvasElement = getCanvas();
canvas.toBlob((blob: Blob) => {
this.service.create(blob).pipe(first()).subscribe((response: boolean) => {
this.isSuccessful = response;
this.cdr.detectChanges();
});
}, 'image/png', 1);
}
Now, this works. But why is it needed here? In all other cases, when I used an arrow function like this, no change detector was necessary. The toBlob()
method seems to be different that way.
PS: The cdr
is also not needed, when the service.create()
method is outside the toBlob()
method.
Change detection is not triggered because canvas.toBlob
executes the callback outside of the Angular Zone. An alternative to calling ChangeDetectorRef.detectChanges
is to make sure that the code is executed inside the Angular zone with NgZone.run:
import { NgZone } from '@angular/core';
...
constructor(private ngZone: NgZone) { }
canvas.toBlob((blob: Blob) => {
this.ngZone.run(() => {
// Run the code here
});
}, 'image/png', 1);
See this stackblitz for a demo.