On initialisation I retrieve all data from API, so the benefit object gets filled out with data.
After that I call another API to get the image data, and fill out the corresponding object with correct base64 data.
So the DOM is written when I try to run this Pipe. And even though console.log(base64data);
prints correct data, it does not show up in DOM. It is always <img _ngcontent-ple-c114="" src="">
in my application.
So I know the first API-calls is correct because the Pipe returns correct base64 string....but it does not set it to src in Benefits.component.html.
Why does it not update the Benefits.component.html?
Benefits.component.html
<div *ngFor="let benefit of benefits">
<div >
<img [src]="benefit.logofile_base64 | returnBase64FromBlob" >
</div>
</div>
Benefits.pipe.ts
@Pipe({
name: 'returnBase64FromBlob'
})
export class ReturnBase64FromBlob implements PipeTransform {
constructor() { }
transform(value: any ): string {
if (!value)
return "";
var reader = new FileReader();
reader.readAsDataURL(value);
reader.onloadend = function () {
var base64data = reader.result;
console.log("base64data - crmpipe");
console.log(base64data);
return base64data;
}
return "";
}
}
Result in DOM:
<img _ngcontent-ple-c114="" src="">
Edit: Just to ellobarate. The pipe runs two times, first time the console.log(base64data) returns blank, because value is blank. But second time the console.log returns correct data.
CodePudding user response:
Even though you define the onloadend
function and its callback fires, the pipe is always returning an empty string.
There may be a better way to accomplish this, but the first thing that comes to mind is to return a promise or an observable that fires when the onloadend
event occurs.
I think something like this would work:
transform(value: any ): string {
if (!value)
return of('');
const reader = new FileReader();
reader.readAsDataURL(value);
reader.onloadend = function () {
return reader.result;
}
return fromEvent(reader, 'loadend');
Then in template, you must use async
pipe:
<img [src]="benefit.logofile_base64 | returnBase64FromBlob | async" >
CodePudding user response:
@BizzyBob helped me a lot and I will give him correct answer.
But I had to do some adoptions, and wanted to share them:
@Pipe({
name: 'returnBase64FromBlob',
pure: true,
})
export class ReturnBase64FromBlob implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(value: Blob): any {
if (!value)
return of("");
const reader = new FileReader();
reader.readAsDataURL(value);
reader.onloadend = function () {
return reader.result;
}
return fromEvent<ProgressEvent>(reader, 'loadend')
.pipe(
map(e => {
const targetImg = (e.target as FileReader | null);
if (targetImg?.result) {
return this.sanitizer.bypassSecurityTrustUrl(targetImg?.result.toString());
} else {
return "";
}
}
)
);
}
}
Now it is solved.