-2

I have some images stored on my backend which are protected by authentication.

My application has a http interceptor set up to call my backend with a token once it's logged in.

I've tried the following code to load an image after the page has loaded but I'm hitting some issues:

html:

<img [src]='loadImage(example["File Name"])'/>
<figcaption>{{example['Caption']}}</figcaption>

ts:

loadImage(imgFileName)
{
  console.log("Load Image");

  let url = `${this.apiUrl}/images/${imgFileName}`;

  console.log(url);

  return this.httpClient.get(url);
}

Console output:

enter image description here

Network tab:

enter image description here

TomSelleck
  • 6,706
  • 22
  • 82
  • 151
  • 1
    If you're setting the image URL, shouldn't it be just `return url;`? Doesn't make sense to pass an Ajax call to the image's src attribute. – Guy Incognito Jun 15 '20 at 20:30
  • @GuyIncognito I don't want to set the URL, I have that already - I need to load the image using Angulars http client so it will use my applications authentication token in the image request. – TomSelleck Jun 15 '20 at 20:48
  • Sure, but it still doesn't make any sense to put the Ajax request into the src attribute. You'll have to convert the result to base64 first. – Guy Incognito Jun 15 '20 at 20:51
  • Ah okay.. I was trying the answers listed here but didn't have any luck: https://stackoverflow.com/questions/40511173/angular-2-image-src-as-function-return – TomSelleck Jun 15 '20 at 20:52

1 Answers1

2

There are multiple issues here.

  1. If example["File Name"] denotes a property of an object, why would there be a space in the property name?

  2. Binding a function to a property ([src] here) might be triggered multiple times if you aren't controlling the change detection strategy.

  3. If you're trying to bind an observable (this.http.get() here), you need to use the async pipe: [src]='loadImage(example["File Name"]) | async'. I don't condone this statement.

The better approach would be to modify the object in the controller to add the URLs and use them directly.

Controller

example = [
  { name: 'sample', Caption: 'sample', ... },
  { name: 'sample', Caption: 'sample', ... },
  { name: 'sample', Caption: 'sample', ... },
  ...
];

ngOnInit() {
  this.example.forEach(item => {
    item['url'] = this.apiUrl + '/images/' + item['name'];
  });
}

Template

<ng-container *ngFor="let image of example">
  <img [src]="image?.url"/>
  <figcaption>{{image['Caption']}}</figcaption>
</ng-container>
ruth
  • 29,535
  • 4
  • 30
  • 57
  • Thanks for the reply - the space is correct, it comes from a JSON key with a space in it. I can't use the URLs directly because then it bypasses my http interceptor which contains a token required to load the images. – TomSelleck Jun 15 '20 at 20:46
  • @TomSelleck: In that case, try if this solution helps: https://stackoverflow.com/a/49115219/6513921 – ruth Jun 15 '20 at 20:59
  • 1
    This is a great explanation. – Ali Celebi Jan 12 '22 at 20:42