Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2: How to handle a async image (blob) request?

I am trying to request a image via a secured api. At the moment I got the following to work (see all the resources I use below.

import { AssetsService } from '../../services/AssetsService';
import { Component } from '@angular/core';

@Component({
    templateUrl: 'home.html',
})
export class HomePage {

    public img;

    constructor(
        public assets_service: AssetsService
    ) { }

    public async ionViewDidEnter() {
        this.img = await this.assets_service.picture_request('test.png');
    }
}

My view

<img [src]="img | safe" />

Now I've seen the async pipe that looks promising. As you might have guessed, I really don't want to use a viewmodel property for each of the image I want to request via the api like used above.

I want to to use the async call picture_request straight from the html view. That will save me all the plumbing in the viewmodel. From what I've read somethings like something like this should work, but only it doesnt sadly.

<img [src]="assets_service.picture_request('test.png') | async | safe" />

I am not sure if I am using the async pipe correctly or using the right approach. If I'm not what should my approach be? Any help is appreciated. FYI: I am using angular 2 in combination with ionic 2.

My other used resources:

My Safe pipe

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({ name: 'safe' })
export class SafePipe implements PipeTransform {
    constructor(
        private sanitizer: DomSanitizer
    ) { }
    transform(url) {
        return this.sanitizer.bypassSecurityTrustResourceUrl(url);
    }
} 

My assets service

import 'rxjs/Rx';
import { Headers, RequestOptions, ResponseContentType } from '@angular/http';
import { Injectable } from '@angular/core';
import { AppConfiguration } from '../app/AppConfiguration';
import { AuthHttp } from 'angular2-jwt';

@Injectable()
export class AssetsService {

    constructor(
        private auth_http: AuthHttp
    ) { }

    /**
     * Fetches a image by filename by filename and converts it to a blob/object url
     */ 
    public picture_request(filename: string) {
        return this.auth_http.post(AppConfiguration.base_url + 'assets/image',
            JSON.stringify({
                filename: filename
            }), 
            new RequestOptions({
                responseType: ResponseContentType.Blob,
                headers: new Headers({
                    'Content-Type': 'application/x-www-form-urlencoded'
                })
            })
            .map(res => res.blob())
            .map(blob => URL.createObjectURL(blob))
            .toPromise();
    }
}
like image 929
Tom Aalbers Avatar asked Feb 06 '17 19:02

Tom Aalbers


1 Answers

I've found a solution which worked for me. I created a custom component.

import { Component, Input } from '@angular/core';
import { AssetsService } from '../../services/AssetsService';

@Component({
    selector: 'async-image',
    template: `<img [src]="img | safe" />`
})
export class AsyncImageComponent {

    @Input() filename: string;
    public img: any;

    constructor(
        public assets_service: AssetsService
    ) { }

    public async ngOnInit(): Promise<void> {
       this.img = await this.assets_service.picture_request(this.filename);
    }
}

Which I can use like this.

<async-image filename="{{image.filename}}"></async-image>
like image 133
Tom Aalbers Avatar answered Oct 18 '22 22:10

Tom Aalbers