Angular2: Mostrar imagen de marcador de posición si img src no es válido


Objetivo: Cargar una imagen con una fuente dinámica. Si no se encuentra ninguna imagen, cargue una imagen de marcador de posición en su lugar.

Esto debería demostrar lo que estoy tratando de hacer, pero no se como establecer condicionalmente validImage basado en si el primer img src es válido.

<img *ngif="validImage" class="thumbnail-image" src="./app/assets/images/{{image.ID}}.jpg" alt="...">
<img *ngif="!validImage" class="thumbnail-image" src="./app/assets/images/placeholder.jpg" alt="...">

ValidImage debe ser true si src=". / app / assets / images / {{image.ID}}. jpg " devuelve una imagen. De lo contrario devolvería false y solo debería aparecer la segunda etiqueta img.

Hay trabajo obvio arounds como almacenar una lista de todas las fuentes de imágenes válidas, pero estoy pensando que hay una mejor manera de lograr esto.

Cualquier sugerencia sobre la mejor manera de implementar esto en Angular2 sería muy apreciada.

Author: user2263572, 2016-03-16

8 answers

La mejor manera de manejar enlaces de imágenes rotas es usar el evento onError para la etiqueta <img>:

<img  class="thumbnail-image" src="./app/assets/images/{{image.ID}}.jpg"
      onError="this.src='./app/assets/images/placeholder.jpg';"  alt="..." />
 83
Author: JanR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-16 03:55:28

Me encontré con una necesidad similar. Quería predeterminar un píxel transparente de 1X1 si una url de img era nula o devolvía un 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() {
        return this.defaultImg;
    }
    public checkPath(src) {
        return src ? src : this.defaultImg;
    }
}
 21
Author: Chris Wheaton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-15 21:16:44
<img [src]="pic" (error)="setDefaultPic()">

Y en algún lugar de su clase componente:

setDefaultPic() {
  this.pic = "assets/images/my-image.png";
}
 14
Author: Tiago Bértolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-12 17:00:31
<img class="thumbnail-image" src="getImage()" alt="...">

getImage():string{  //I don't know how would you handle your situation here. But you can think of it.

  if (this.validImage) // I don't know how would you manage validImage here.
  {
     return this.validImagePath;
  }

   return this.placeholderImagePath;
}
 1
Author: micronyks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-16 03:54:35

He creado un componente personalizado que utiliza una imagen de marcador de posición si la imagen aún no está cargada o si se produce un error al cargarla:

img.componente.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.componente.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>

Entonces puedes usarlo como:

<my-img [src]="src" [alt]="alt" [default]="DEFAULT_IMAGE"></my-img>

PD: Verifico de antemano si la imagen está almacenada en caché para evitar que la imagen parpadee (normalmente cuando se vuelve a renderizar un componente que tiene la imagen dentro) entre el marcador de posición y la imagen (si está almacenada en caché, mostrar la imagen incluso antes de que la bandera cargada se establezca en true). Puede descomentar el registro en la función isCached para ver si sus imágenes están almacenadas en caché o no.

 1
Author: Lucas Basquerotto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-22 13:21:14
src="validImage ? validImageUrl : placeHolderImgUrl"
 0
Author: robert king,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-16 03:54:42

Hay una forma no Angular2 por CSS puro: Estilizar Imágenes rotas

Pero tenga en cuenta las métricas de soporte del navegador en el artículo.

 0
Author: Vivien Hung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-16 04:09:21

Acabo de hacer esto:

En mi ARCHIVO HTML escribió esto

<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>

Llamé a una función que está en mi componente.ts y pasar el objeto wheres mi url como un parámetro

getImage(result){
if(result.poster_path){
  return this.imageURL+(result.poster_path);
}else return "./assets/noFound.jpg"

Aquí está mi función , primero verifico si la url de la imagen del objeto es diferente de null si es verdadera, entonces devuelvo la url de la imagen de lo contrario devuelvo mi imagen predeterminada "noFound" que está en mis activos de la aplicación.
Espero que ayude!

 0
Author: Jared Josafhat H Z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-11 18:47:59