Image preview directive #461

Open
opened 2016-10-24 13:13:13 +00:00 by BojanKogoj · 23 comments
BojanKogoj commented 2016-10-24 13:13:13 +00:00 (Migrated from github.com)

I've been missing image preview with this library, so I made my own. Unlike #368 solution multiple images can be previewed.
It's not perfect (doesn't detect if it's not an image), but if @valorkin thinks this could be somehow included I'm up for it. Should temporarily solve #294

image-preview.directive.ts

import { Directive, ElementRef, Input, Renderer, OnChanges, SimpleChanges } from '@angular/core';

@Directive({ selector: 'img[imgPreview]' })

export class ImagePreview {

    @Input() image: any;

    constructor(private el: ElementRef, private renderer: Renderer) { }

    ngOnChanges(changes: SimpleChanges) {

        let reader = new FileReader();
        let el = this.el;

        reader.onloadend = function (e) {
            el.nativeElement.src = reader.result;
        };

        if (this.image) {
            return reader.readAsDataURL(this.image);
        }

    }

}

Example usage

  • Add reference to ngModule
  • Use it like this
<div *ngFor="let item of uploader.queue" class="media">
    <div class="media-left">
        <img src="" imgPreview [image]="item?._file" class="media-object" />
    </div>
    <div class="media-body">
        <p>{{ item?.file?.name }}</p>
    </div>
</div>
  • Will be displayed something like this (make sure to set sizes with css)

screen shot 2016-10-24 at 14 59 53

I've been missing image preview with this library, so I made my own. Unlike #368 solution multiple images can be previewed. It's not perfect (doesn't detect if it's not an image), but if @valorkin thinks this could be somehow included I'm up for it. Should temporarily solve #294 ### image-preview.directive.ts ``` import { Directive, ElementRef, Input, Renderer, OnChanges, SimpleChanges } from '@angular/core'; @Directive({ selector: 'img[imgPreview]' }) export class ImagePreview { @Input() image: any; constructor(private el: ElementRef, private renderer: Renderer) { } ngOnChanges(changes: SimpleChanges) { let reader = new FileReader(); let el = this.el; reader.onloadend = function (e) { el.nativeElement.src = reader.result; }; if (this.image) { return reader.readAsDataURL(this.image); } } } ``` ### Example usage - Add reference to ngModule - Use it like this ``` <div *ngFor="let item of uploader.queue" class="media"> <div class="media-left"> <img src="" imgPreview [image]="item?._file" class="media-object" /> </div> <div class="media-body"> <p>{{ item?.file?.name }}</p> </div> </div> ``` - Will be displayed something like this (make sure to set sizes with css) ![screen shot 2016-10-24 at 14 59 53](https://cloud.githubusercontent.com/assets/634075/19646855/b25ecc72-99fb-11e6-87ec-8242c2ee5a91.png)
atais commented 2016-12-02 10:01:44 +00:00 (Migrated from github.com)

+1

+1
Sathishchary commented 2016-12-28 14:40:06 +00:00 (Migrated from github.com)

Can any one tried how to show the video preview .I need to show the preview of a video before it is uploaded.?
thanks

Can any one tried how to show the video preview .I need to show the preview of a video before it is uploaded.? thanks
rainstormza commented 2017-02-06 03:40:58 +00:00 (Migrated from github.com)

+1

+1
edmondtm commented 2017-05-19 12:56:57 +00:00 (Migrated from github.com)

Thank you. It works like magic.

Thank you. It works like magic.
vlaco commented 2017-06-29 10:12:11 +00:00 (Migrated from github.com)

Thanks! I used this for image preview before upload. But does anyone have an idea how to show preview in case the user wants to upload a pdf file?

Thanks! I used this for image preview before upload. But does anyone have an idea how to show preview in case the user wants to upload a pdf file?
matheusdavidson commented 2017-09-11 16:33:00 +00:00 (Migrated from github.com)

Thank you @BojanKogoj, your solution works very well!

Thank you @BojanKogoj, your solution works very well!
tobisinghania commented 2017-10-13 15:08:47 +00:00 (Migrated from github.com)

Will this be integrated into the plugin at some point?

Will this be integrated into the plugin at some point?
adrianfaciu commented 2017-10-22 09:49:33 +00:00 (Migrated from github.com)

There is no open pull request with this. If one is provided it will be investigated and probably merged.

There is no open pull request with this. If one is provided it will be investigated and probably merged.
AngularTx commented 2017-11-11 08:29:34 +00:00 (Migrated from github.com)

Hi
can we preview the pdf file ?

Hi can we preview the pdf file ?
vlaco commented 2017-11-13 09:52:55 +00:00 (Migrated from github.com)

I made a workaround so that it check file type too, if the file is pdf it shows an iframe element, and if its any other file format (png, jpg, jpeg) it shows an img element.

I made a workaround so that it check file type too, if the file is pdf it shows an iframe element, and if its any other file format (png, jpg, jpeg) it shows an img element.
GPNandhini commented 2018-02-26 10:16:27 +00:00 (Migrated from github.com)

Hi,
If i am using this code getting error , please find the below bold lines what we getting error

Can't bind to 'image' since it isn't a known property of 'img'.
"<img src="" imgPreview [ERROR ->][image]="item?._file" class="media-object" />

Please help on this to resolved

Hi, If i am using this code getting error , please find the below bold lines what we getting error **Can't bind to 'image' since it isn't a known property of 'img'. "<img src="" imgPreview [ERROR ->][image]="item?._file" class="media-object" />** Please help on this to resolved
BojanKogoj commented 2018-02-26 10:21:27 +00:00 (Migrated from github.com)

@Pushpanandhini you most probably forgot to import Directive.

@Pushpanandhini you most probably forgot to import Directive.
GPNandhini commented 2018-02-28 07:27:39 +00:00 (Migrated from github.com)

@BojanKogoj , thank you image preview working ..
Anyone have idea to preview the Video, Doc related files uploading?

@BojanKogoj , thank you image preview working .. Anyone have idea to preview the Video, Doc related files uploading?
Sathishchary commented 2018-02-28 08:36:33 +00:00 (Migrated from github.com)

for video preview, use like this,

<video id="my-video" controls preload="auto" width="250" height="150">
  <source [src]='videoPreviewPath' type='video/mp4'>
</video>

component:
videoPreviewPath = 'http://vjs.zencdn.net/v/oceans.mp4';

for video preview, use like this, ``` <video id="my-video" controls preload="auto" width="250" height="150"> <source [src]='videoPreviewPath' type='video/mp4'> </video> ``` component: `videoPreviewPath = 'http://vjs.zencdn.net/v/oceans.mp4';`
isabelatelles commented 2018-03-09 21:16:58 +00:00 (Migrated from github.com)

I've done some modifications to detect if it is an image or a pdf file. It's pretty simple and you can easily adjust to your preferences of file type.

image-preview.directive.ts

import { Directive, ElementRef, Input, Renderer, OnChanges, SimpleChanges } from '@angular/core';

@Directive({ selector: '[imgPreview]' })

export class ImagePreviewDirective {

    @Input() private media: any;
    @Input() private type: any;

    constructor(private el: ElementRef, private renderer: Renderer) { }

    ngOnChanges(changes: SimpleChanges) {

        let reader = new FileReader();
        let el = this.el;

        if (this.type === 'application/pdf') {
            reader.onloadend = function (e) {
                el.nativeElement.data = reader.result;
            };
        } else if (this.type.split('/')[0] === 'image') {
            reader.onloadend = function (e) {
                el.nativeElement.src = reader.result;
            };
        }
        

        if (this.media) {
            return reader.readAsDataURL(this.media);
        }

    }
}

image-preview.component.ts

import { Component, OnInit } from '@angular/core';
import { ImageService } from '../shared/image.service';

@Component({
  selector: 'img-preview',
  templateUrl: './img-preview.component.html',
  styleUrls: ['./img-preview.component.scss']
})

export class ImgPreviewComponent implements OnInit {
  uploader: any;
  file: any;
  type: string;

  constructor(private imageService: ImageService) {
  }

  ngOnInit() {
    this.uploader = this.imageService.uploader.queue[0];
    this.file = this.imageService.uploader.queue[0]._file;
    if (this.imageService.uploader.queue[0].file.type === 'application/pdf')
      this.type = 'application/pdf';
    else if (this.imageService.uploader.queue[0].file.type.split('/')[0] === 'image')
      this.type = 'image';
  }
}

Example usage

<img *ngIf="type === 'image'"
          src="" imgPreview [media]="file" [type]="type"
          class="image">
<object *ngIf="type === 'application/pdf'"
            data="" imgPreview [media]="file" [type]="type"
            type="application/pdf" class="image-pdf"></object>
I've done some modifications to detect if it is an image or a pdf file. It's pretty simple and you can easily adjust to your preferences of file type. **image-preview.directive.ts** ``` import { Directive, ElementRef, Input, Renderer, OnChanges, SimpleChanges } from '@angular/core'; @Directive({ selector: '[imgPreview]' }) export class ImagePreviewDirective { @Input() private media: any; @Input() private type: any; constructor(private el: ElementRef, private renderer: Renderer) { } ngOnChanges(changes: SimpleChanges) { let reader = new FileReader(); let el = this.el; if (this.type === 'application/pdf') { reader.onloadend = function (e) { el.nativeElement.data = reader.result; }; } else if (this.type.split('/')[0] === 'image') { reader.onloadend = function (e) { el.nativeElement.src = reader.result; }; } if (this.media) { return reader.readAsDataURL(this.media); } } } ``` **image-preview.component.ts** ``` import { Component, OnInit } from '@angular/core'; import { ImageService } from '../shared/image.service'; @Component({ selector: 'img-preview', templateUrl: './img-preview.component.html', styleUrls: ['./img-preview.component.scss'] }) export class ImgPreviewComponent implements OnInit { uploader: any; file: any; type: string; constructor(private imageService: ImageService) { } ngOnInit() { this.uploader = this.imageService.uploader.queue[0]; this.file = this.imageService.uploader.queue[0]._file; if (this.imageService.uploader.queue[0].file.type === 'application/pdf') this.type = 'application/pdf'; else if (this.imageService.uploader.queue[0].file.type.split('/')[0] === 'image') this.type = 'image'; } } ``` **Example usage** ``` <img *ngIf="type === 'image'" src="" imgPreview [media]="file" [type]="type" class="image"> <object *ngIf="type === 'application/pdf'" data="" imgPreview [media]="file" [type]="type" type="application/pdf" class="image-pdf"></object> ```
shakesBeardZ commented 2018-03-13 23:53:52 +00:00 (Migrated from github.com)

@isabelatelles Like your implementation , tried it it's working thankxxxx

@isabelatelles Like your implementation , tried it it's working thankxxxx
erperejildo commented 2018-04-17 11:14:41 +00:00 (Migrated from github.com)

Thanks to @BojanKogoj and to @isabelatelles for these awesome directives

Thanks to @BojanKogoj and to @isabelatelles for these awesome directives
JulianSalomon commented 2018-04-26 15:45:43 +00:00 (Migrated from github.com)

Thanks for the implementation @BojanKogoj and the improvements @isabelatelles.

I made some modifications that makes the code more clean:

  1. Renderer is not used, can be removed.
  2. If you get the File object, you don't need the type too, this can be retrieved with the object.
  3. Is unnecessary to make the return.
  4. String have the method startsWith(), then the split can be replaced with this.
  5. Validation of existent file should be done at start (If not, get the type of the file will throw an error).

media-preview.directive.ts

import { Directive, ElementRef, Input, Renderer, OnChanges, SimpleChanges } from '@angular/core';

@Directive({ selector: '[mediaPreview]' })

export class MediaPreviewDirective implements OnChanges {
  @Input() private media: File;

  constructor(private el: ElementRef) { }

  ngOnChanges(changes: SimpleChanges) {
    if (!this.media) {
      return;
    }
    const reader = new FileReader();
    const el = this.el;
    if (this.media.type === 'application/pdf') {
      reader.onloadend = () => el.nativeElement.data = reader.result;
    } else if (this.media.type.startsWith('image')) {
      reader.onloadend = () => el.nativeElement.src = reader.result;
    }
    reader.readAsDataURL(this.media);
  }
}

Usage

<div *ngFor="let item of uploader.queue" class="media">
    <div class="media-left">
        <!-- Image --><!-- Both of the two next lines produce the same result -->
        <img src mediaPreview [media]="item?._file" class="media-object" />
        <img src mediaPreview [media]="item?.file?.rawFile" class="media-object" />
        <!-- PDF -->
        <object data mediaPreview [media]="item._file" class="image-pdf"></object>
    </div>
</div>

Note: If you want include the preview of both (Image and PDF), you can add *ngIf statement as follows:

  • *ngIf="item?._file.type === 'application/pdf'" in <object>
  • *ngIf="item?._file.type.startsWith('image')" for <img>
Thanks for the implementation @BojanKogoj and the improvements @isabelatelles. I made some modifications that makes the code more clean: 1. Renderer is not used, can be removed. 2. If you get the File object, you don't need the type too, this can be retrieved with the object. 3. Is unnecessary to make the return. 4. String have the method startsWith(), then the split can be replaced with this. 5. Validation of existent file should be done at start (If not, get the type of the file will throw an error). **media-preview.directive.ts** ``` import { Directive, ElementRef, Input, Renderer, OnChanges, SimpleChanges } from '@angular/core'; @Directive({ selector: '[mediaPreview]' }) export class MediaPreviewDirective implements OnChanges { @Input() private media: File; constructor(private el: ElementRef) { } ngOnChanges(changes: SimpleChanges) { if (!this.media) { return; } const reader = new FileReader(); const el = this.el; if (this.media.type === 'application/pdf') { reader.onloadend = () => el.nativeElement.data = reader.result; } else if (this.media.type.startsWith('image')) { reader.onloadend = () => el.nativeElement.src = reader.result; } reader.readAsDataURL(this.media); } } ``` **Usage** ``` <div *ngFor="let item of uploader.queue" class="media"> <div class="media-left"> <!-- Image --><!-- Both of the two next lines produce the same result --> <img src mediaPreview [media]="item?._file" class="media-object" /> <img src mediaPreview [media]="item?.file?.rawFile" class="media-object" /> <!-- PDF --> <object data mediaPreview [media]="item._file" class="image-pdf"></object> </div> </div> ``` Note: If you want include the preview of both (Image and PDF), you can add `*ngIf` statement as follows: - `*ngIf="item?._file.type === 'application/pdf'"` in `<object>` - `*ngIf="item?._file.type.startsWith('image')"` for `<img>`
wellingtonfoz commented 2018-05-19 07:14:40 +00:00 (Migrated from github.com)

Thank you so much! You saved me!!!!

Thank you so much! You saved me!!!!
bdebon commented 2019-03-18 09:59:12 +00:00 (Migrated from github.com)

@JulianSalomon and @isabelatelles thanks for sharing these valuable improvements! It works like a charm.

@JulianSalomon and @isabelatelles thanks for sharing these valuable improvements! It works like a charm.
patelmurtuza commented 2019-11-22 15:04:59 +00:00 (Migrated from github.com)

@BojanKogoj, I was looking for this from long time, finally got it. highly appreciate. thanks a lot

@BojanKogoj, I was looking for this from long time, finally got it. highly appreciate. thanks a lot
patelmurtuza commented 2019-11-22 15:05:40 +00:00 (Migrated from github.com)

it works awsome with ng2FileSelect

it works awsome with ng2FileSelect
canalrubi commented 2022-08-22 17:29:30 +00:00 (Migrated from github.com)

Muchas gracias! Thank very much! @BojanKogoj

Muchas gracias! Thank very much! @BojanKogoj
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dc/ng2-file-upload#461