Reputation: 187
I am having difficulties understanding the following:
I have an Image object:
export class Image {
id: string;
imageName: string;
imageDesc: string;
base64?: string; // optional for future converting
}
I then define an array of objects:
export const mockImages: Image[] = [
{
id: 'image1',
imageName: 'image1.jpg',
imageDesc: 'Description of the first picture.',
},
{
id: 'image2',
imageName: 'image2.jpg',
imageDesc: 'Description of the second picture.',
},
{
id: 'image3',
imageName: 'image3.jpg',
imageDesc: 'Description of the third picture.',
}
]
In the ts file I load the data and also start the conversion
ngOnInit(): void {
this.imageData = mockImages;
this.myService.convertImg();
}
In my html, I loop through this data, and while they don´t have specified the fourth parameter base64, I want to conditionaly show loading spinner instead of the image:
<div *ngFor="let data of imageData; let i = index">
<div [hidden]="!data[i]?.base64">
<img
(click)="onPreviewImage(i)"
[src]="data.base64"
[alt]="data.imageDesc"
/>
</div>
<app-loading-tab [hidden]="data[i]?.base64"></app-loading-tab>
</div>
convertImg() function in the myService. I am also defining the mockImages and mockImagesPath property.
convertImg(): void {
const numberOfFiles = this.mockImages.length;
for (let i = 0; i < numberOfFiles; i++) {
this.http
.get(`${this.mockImagesPath}/${this.mockImages[i].imageName}`, {responseType: 'blob'})
.subscribe((res) => {
const reader = new FileReader();
reader.onloadend = () => {
this.mockImages[i].base64 = reader.result as string;
};
reader.readAsDataURL(res);
});
}
}
But this approach is not doing what I would expect - which is conditionally show and hide loader while data is being loaded / and is already displayed. I always see the loading spinners as if the conversion was not recognized.
Can you tell me what am I doing wrong?
Upvotes: 0
Views: 452
Reputation: 31
My suggestion would be to create a Subject on your service class, something like
public imageConverted = new Subject<Image>();
Then in your convert method, notify whenever an image is done converting:
convertImg(): void {
const numberOfFiles = this.mockImages.length;
for (let i = 0; i < numberOfFiles; i++) {
this.http
.get(`${this.mockImagesPath}/${this.mockImages[i].imageName}`, {responseType: 'blob'})
.subscribe((res) => {
const reader = new FileReader();
reader.onloadend = () => {
this.mockImages[i].base64 = reader.result as string;
this.imageConverted.next(this.mockImages[i]);
};
reader.readAsDataURL(res);
});
}
}
Finally in your component subscribe to the event and update the image that's done converting:
ngOnInit(): void {
this.imageData = mockImages;
this.myService.imageConverted.subscribe({
next: (image) => {
const index = this.imageData.findIndex(i => i.id === image.id);
if (index > -1) {
this.imageData[index] = image;
}
}
});
this.myService.convertImg();
}
Upvotes: 1