I have a page to display the "Beer" information on my Angular project. I receive the Beer information on the route snapshot, it's working. Then I get the name of the beer's image and access an API to get the image. Everything works, but in the html, all fields appears, only the image doesn't.
I have the same code on the form and there the image appears. What I'm doing wrong?
Here's the code for the component:
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
NO_ERRORS_SCHEMA,
OnInit
} from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatSidenavModule } from '@angular/material/sidenav';
import { ActivatedRoute } from '@angular/router';
import { MatListModule } from '@angular/material/list';
import { Beer } from '../../model/beer';
import { CommonModule, Location, NgFor, NgIf } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { StartComponent } from '../../shared/components/star-rating/star-rating.component';
import { FileUploadService } from '../../services/file-upload.service';
@Component({
selector: 'app-beer-view',
templateUrl: './beer-view.component.html',
styleUrls: ['./beer-view.component.scss'],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
NgIf,
NgFor,
MatSidenavModule,
MatButtonModule,
MatListModule,
MatCardModule,
MatToolbarModule,
MatDividerModule,
MatIconModule,
StartComponent,
CommonModule
],
schemas: [NO_ERRORS_SCHEMA]
})
export class BeerViewComponent implements OnInit {
beer!: Beer;
fileName? = '';
imageShow: any;
isImageLoading: boolean = true;
constructor(
private route: ActivatedRoute,
private changeDetectorRef: ChangeDetectorRef,
private location: Location,
private uploadService: FileUploadService) { }
ngOnInit() {
this.beer = this.route.snapshot.data['beer'];
this.fileName = this.beer.image;
this.obtainImage();
}
onCancel() {
this.location.back();
}
obtainImage(): void {
console.log("obtain image");
console.log(this.fileName);
this.isImageLoading = true;
this.uploadService.getFile(this.fileName).subscribe(
(data) => {
this.createImageFromBlob(data);
console.log("ok");
this.isImageLoading = false;
console.log(this.isImageLoading);
},
(error) => {
console.log("erro");
this.isImageLoading = false;
console.log(error);
}
);
}
createImageFromBlob(image: Blob) {
let reader = new FileReader();
reader.addEventListener(
'load',
() => {
this.imageShow = reader.result;
console.log(this.imageShow);
},
false
);
if (image) {
reader.readAsDataURL(image);
}
}
}
Here is the code for the view component:
<mat-card appearance="outlined">
<mat-toolbar color="primary">
<h1>Beers Detail</h1>
</mat-toolbar>
<mat-table class="mat-elevation-z8">
<mat-list>
<mat-list-item><b>NAME : </b>{{ beer.name }}</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item><b>TYPE :</b> {{ beer.type }}</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item><b>ORIGIN :</b> {{ beer.origin }}</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item
><b>PRICE :</b>
{{ beer.price | currency : "EUR" : "symbol" : "1.2-2" }}</mat-list-item
>
<mat-divider></mat-divider>
<mat-list-item><b>RATING :</b> {{ beer.rating }} </mat-list-item>
<mat-divider></mat-divider>
<mat-list-item *ngIf="!isImageLoading">
<img [src]="imageShow" alt="Beer Image">
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-card-actions class="actions-center">
<button
mat-raised-button
(click)="onCancel()"
class="btn-space"
type="button" >
<mat-icon aria-hidden="false" fontIcon="keyboard_arrow_left"></mat-icon>
Back
</button>
</mat-card-actions>
</mat-table>
</mat-card>
The screen:
I have add some log, and I can see that I have got the image ok:
It's working on the form page:
I already tried with a fix URL, and it works. I don't know why the image does not appear.
I have tried to put it outside the <mat-card>
, I deleted everything but the line:
<img [src]="imageShow" alt="Beer Image">
I tried:
<img src="{{'data:image/jpg;base64,' + imageShow}}" />
<img src="{{ image_path }}" />
But it doesn't work.
Thanks!
Since you're using OnPush change detection, you need to call change detection manually after assigning the image:
this.imageShow = reader.result;
this.changeDetectorRef.markForCheck();
also, you should sanitize image src with DomSanitizer
this.imageShow = this.sanitizer.bypassSecurityTrustResourceUrl(reader.result);