Goal: Load an image with a dynamic source. If no image is found, then load a placeholder image instead.
This should demonstrate what I\'m trying to
The best way to handle broken image links is the use the onError
event for the <img>
tag:
<img class="thumbnail-image" src="./app/assets/images/{{image.ID}}.jpg"
onerror="this.src='./app/assets/images/placeholder.jpg';" alt="..." />
<img [src]="pic" (error)="setDefaultPic()">
And somewhere in your component class:
setDefaultPic() {
this.pic = "assets/images/my-image.png";
}
I Just did this :
In my HTML FILE wrote this
<div
(click)="getInfo(results[movie].id)"
*ngFor="let movie of (results | key:'10')"
class="card" style="margin-top:7%;">
<img [src]="getImage(results[movie])" alt="" class="card-img-top pointer"></div>
I called a function that is in my component.ts and pass the object wheres my url as a parameter
getImage(result){
if(result.poster_path){
return this.imageURL+(result.poster_path);
}else return "./assets/noFound.jpg"
Heres my function , first I verify if the object image url is different from null if is true then I return the image url else i return my default "noFound" image that is in my app assets.
Hope it helps!
src="validImage ? validImageUrl : placeHolderImgUrl"
I ran into a similar need. I wanted to default to a 1X1 transparent pixel if an img url was null or returned an error (404 etc).
import { Directive, Input } from '@angular/core';
@Directive({
selector: 'img[src]',
host: {
'[src]': 'checkPath(src)',
'(error)': 'onError()'
}
})
export class DefaultImage {
@Input() src: string;
public defaultImg: string = '{YOUR_DEFAULT_IMG}';
public onError() {
this.src = this.defaultImg;
}
public checkPath(src) {
return src ? src : this.defaultImg;
}
}
Markup
<img [src]="{DESIRED_IMAGE_SOURCE}" />
I've created a custom component that uses a placeholder image if the image is still not loaded or if an error occurs when loading it:
img.component.ts:
import { Component, Input, OnChanges } from '@angular/core';
@Component({
selector: 'my-img',
templateUrl: 'img.component.html',
})
export class ImgComponent implements OnChanges {
@Input()
public src: string;
@Input()
public default: string;
@Input()
public alt: string;
public cached = false;
public loaded = false;
public error = false;
private lastSrc: string;
constructor() { }
public ngOnChanges() {
if (this.src !== this.lastSrc) {
this.lastSrc = this.src;
this.loaded = false;
this.error = false;
this.cached = this.isCached(this.src);
}
if (!this.src) {
this.error = true;
}
}
public onLoad() {
this.loaded = true;
}
public onError() {
this.error = true;
}
private isCached(url: string): boolean {
if (!url) {
return false;
}
let image = new Image();
image.src = url;
let complete = image.complete;
// console.log('isCached', complete, url);
return complete;
}
}
img.component.html:
<ng-container *ngIf="!cached">
<img
*ngIf="!error"
[hidden]="!loaded"
[src]="src"
[alt]="alt"
(load)="onLoad()"
(error)="onError()"
>
<img
*ngIf="default && (error || !loaded)"
[src]="default"
[alt]="alt"
>
</ng-container>
<ng-container *ngIf="cached">
<img
*ngIf="!error"
[src]="src"
[alt]="alt"
(error)="onError()"
>
<img
*ngIf="default && error"
[src]="default"
[alt]="alt"
>
</ng-container>
Then you can use it like:
<my-img [src]="src" [alt]="alt" [default]="DEFAULT_IMAGE"></my-img>
PS: I verify beforehand if the image is cached to avoid the image blinking (normally when a component that has the image inside is re-rendered) between the placeholder and the image (if it is cached, I show the image even before the loaded flag be set to true). You can uncomment the log in the isCached
function to see if your images are cached or not.