4

I have an Angular 7 app in which I am displaying a div background image. But sometimes link is broken.

My image is bound in my HTML like this

<div [ngStyle]="{'background-image': 'url(' + row?.coverUrl + ')', 'background-size': 'cover', 'background-position' : 'center'}" class="img-area cursor-pointer" (click)="navigateToCOmpany(row)" *ngIf="row.coverUrl !== ''">
</div>

The problem is that sometimes row?.coverUrl is broken link. So how can I detect that link is broken so that I can bind a default image?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Fahad Hassan
  • 781
  • 10
  • 20
  • As an option invoke a `get` request to the background image url and in case it succeed, all things are ok. In case it errored - you have a problem case. – Rafael Feb 17 '20 at 14:40
  • I don't think it's the proper way to do this. Because if i do like this so for each time for each image will i be hitting one extra get call? Don't you think it will create server overhead? – Fahad Hassan Feb 17 '20 at 14:41
  • `get` requests are cached by server usually.And it should not make a sufficient overhead if your images are not 1gb in size. – Rafael Feb 17 '20 at 14:43
  • row?.coverUrl - is internal url or external ? – Milan Raval Feb 17 '20 at 14:50
  • @MilanRaval external url that might be expire after sometime. – Fahad Hassan Feb 17 '20 at 14:53
  • You can take @Rafael's idea and use a HEAD request instead, which will be much lighter-weight, but still tell you whether the image exists or not. – Heretic Monkey Feb 17 '20 at 14:56
  • Answer to this question looks similar, it has another URL as fallback : https://stackoverflow.com/questions/37588017/fallback-background-image-if-default-doesnt-exist – Milan Raval Feb 17 '20 at 15:09
  • @HereticMonkey how can i make a http request for image? – Fahad Hassan Feb 17 '20 at 15:50
  • Ajax; You're using Angular, so HttpClient is the way to go. – Heretic Monkey Feb 17 '20 at 15:51
  • @HereticMonkey i tried this `get = (): Observable => { return this._http.get(`https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg`, { headers: this.getHeaders()}) }` But on subscribing to it each time i am getting an error – Fahad Hassan Feb 17 '20 at 15:53
  • see this stackblitz https://stackblitz.com/edit/angular-pjavzx – Fahad Hassan Feb 17 '20 at 15:55
  • Sounds like a different problem (likely CORS). Do some research on the error you are getting, and if you can't find anything, ask a new question. – Heretic Monkey Feb 17 '20 at 15:55

4 Answers4

0

There are some workarounds which you can use:

  1. Use an invisible img tag (as suggested by user3723763) and in the error handler update the row.coverUrl which will update your DIV's background image also.
  2. Multiple URLs can be passed in the background-image, pass the fallback image as the 2nd URL and it will start showing if the first one breaks. NOTE: this will correctly work only if your images are not transparent, refer the sample code from here: 2 URLs as background-image
Praveen
  • 263
  • 2
  • 10
0

Although there is no professional solution I still wanted to show the different ways if you like you can use it.

<div [ngStyle]="backgroundObj" class="img-area cursor-pointer"></div>
<img hidden [src]="brokenImageUrl" (error)="doSomethingOnError($event)" />



  brokenImageUrl = null // or try -> 'https://placebeard.it/640x360'; 
  brokeImage =
    'https://serpstat.com/img/blog/how-to-detect-broken-images-on-the-website/16451874451570033394image1-min.png';
  image = 'https://placebeard.it/640x360';
  backgroundObj = {
    width: '500px',
    height: '500px',
    'background-image': 'url(' + this.image + ')',
    'background-repeat': 'no-repeat',
  };
  

  doSomethingOnError(event: any) {
    if (event) {
      this.backgroundObj = {
        width: '500px',
        height: '500px',
        'background-image': 'url(' + this.brokeImage + ')',
        'background-repeat': 'no-repeat',
      };
    }
  }

stackblitz

Behram Bazo
  • 230
  • 2
  • 6
0

I think this is the solution for your problem

 <div [ngStyle]="{'background-image': 'url(' + row.coverUrl? row.coverUrl : 
  deafultUrl + ')', 'background-size': 'cover', 'background-position' : 
  'center'}" class="img-area cursor-pointer" 
  (click)="navigateToCOmpany(row)" *ngIf="row.coverUrl !== ''">
</div>
0

I wanted to have an image with a spinner while loading. For this, I used an Image to load the image, and once loaded, I made a data URL from it that I passed to the <img>. Given this method, I knew exactly when the image was loading, loaded or errored.

Just be wary when changing image to same URL, it might get confused.

Akxe
  • 9,694
  • 3
  • 36
  • 71