7

In my angular 4 application I have to load a thumbnail, So I have img [src] tag. To append the authorization token at the request to load this image I use a custom image pipe and an async pipe. It works good but if I see in the network tab I can see a strange call to null and I think is the async pipe:

Request URL:http://localhost:4200/null

image.pipe

@Pipe({name: 'image'})
 export class ImagePipe implements PipeTransform {
  constructor(private http: Http) {}

  transform(url: string, selfLink?: any, width?: any) {
    /* tell that XHR is going to receive an image as response, so it can be then converted to blob,
      * and also provide your token in a way that your server expects */

    if (selfLink) {
      url = selfLink + url + width;
    }


    const headers = new Headers({'Authorization': 'Bearer ' + localStorage.getItem('token'), 'Content-Type': 'image/jpeg'});
    // specify that response should be treated as blob data
    return this.http.get(url, new RequestOptions({headers: headers, responseType: ResponseContentType.Blob}))
      .map(response => response.blob()) // take the blob
      .switchMap(blob => {
        // return new observable which emits a base64 string when blob is converted to base64
        return Observable.create(observer => {
          const reader = new FileReader();
          reader.readAsDataURL(blob); // convert blob to base64
          reader.onloadend = function() {
            observer.next(reader.result); // emit the base64 string result
          }
        });
      });
  }
}

And this is the component.html

<div class="card-avatar" (click)="openFilePicker()">
  <img class="img pointer" [ngStyle]="{'width.px': 130,'height.px': 130}" *ngIf="links.avatar && imageLink" [src]="(imageLink | image) | async" />
  <img src="../../assets/img/default-avatar.png" class="img pointer" *ngIf="links.avatar === undefined">
</div>

It seems that the async pipe make the call 2 times, 1 is corect and 1 is with error, I don't know why, my image link is never null or undefined because if I print the url in the image pipe I see always the correct link.

this is the call:

enter image description here

Also if I write directly a link into the pipe without any call I still have a null <img [src]="('http://.....:8080/api/v1/medias/1/download' | image) | async" />

How can I solve this null call?

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
Alessandro Celeghin
  • 4,039
  • 14
  • 49
  • 95

2 Answers2

11

Try using [attr.src]=(imageLink | image) | async" instead.

With the attr.<whatever> syntax, nulls prevent the attribute from being added in the first place.

Example: https://stackblitz.com/edit/angular-gitter-btxhuh?file=app%2Fapp.component.html

Amit
  • 4,274
  • 21
  • 25
  • The problem is not here because also if I write manually the image link `[attr.src]="('http://.....:8080/api/v1/users/1/avatar' | image) | async"` still have the null call – Alessandro Celeghin Jan 09 '18 at 09:46
  • Hmm, I think it might be because of the image pipe, can you post the pipe's code? – Amit Jan 09 '18 at 09:58
  • Hmm, sorry, I thought that's a component, so my eyes skipped it. Could you maybe upload this to a plunk somewhere? It's a little hard eye-balling this. – Amit Jan 09 '18 at 13:05
  • sorry but I have some problem to show image with this plunker if I use my pipe I have some CORS problem, check in the html https://stackblitz.com/edit/angular-gitter-b3uyah?file=app%2FimagePipe.ts – Alessandro Celeghin Jan 09 '18 at 14:56
  • I don't understand, I see my plunk with a different image, and with the pipe's code – Amit Jan 09 '18 at 15:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/162825/discussion-between-alessandro-and-amit). – Alessandro Celeghin Jan 09 '18 at 15:04
2

The problem is that src attribute is trying to execute a GET request before the async pipe resolved some value.

It can be solved by using *ngIf and checking if the value you wish to use in src has resolved.

Same with iFrames.

Amit Hadary
  • 498
  • 1
  • 3
  • 11