UNPKG

@bsj/angular-image-picker

Version:
164 lines (134 loc) 6.82 kB
import { Component, ViewChild, OnInit, Input, Output, forwardRef, EventEmitter, ViewChildren, QueryList } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Media } from './media.model' import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { AngularImagePickerImageComponent } from './angular-image-picker-image/angular-image-picker-image.component'; // Used to extend ngForms functions export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AngularImagePickerComponent), multi: true }; @Component({ providers: [ CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR ], selector: 'tzd-angular-image-picker', styles: [".image-picker-wrapper{padding:16px 0}.image-picker-wrapper .click{cursor:pointer}.image-picker-wrapper img{max-width:100%;max-height:100%;display:block;margin:auto;margin-bottom:16px}.image-picker-wrapper .multiple-images-container{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}.image-picker-wrapper .multiple-images-container .multiple-images-image{flex:1 auto;max-width:48%}.image-picker-wrapper .multiple-images-container .multiple-images-image:first-of-type{max-width:100%}.image-picker-wrapper .multiple-images-container .multiple-images-image img{width:100%} "], template: "<div class=\"image-picker-wrapper\"> <div *ngIf=\"(initialModelImages && !changeImageMode) else pickImages\"> <div [ngSwitch]=\"multiple ? true : false\" class=\"click\" (click)=\"changeImageMode = true\"> <div *ngSwitchCase=\"true\" class=\"multiple-images-container\"> <div class=\"multiple-images-image\" *ngFor=\"let initialModelImage of initialModelImages\"> <img [src]=\"initialModelImage\"> </div> </div> <div *ngSwitchCase=\"false\"> <img [src]=\"initialModelImages\"> </div> </div> </div> <ng-template #pickImages> <div *ngIf=\"files\"> <button type=\"button\" mat-mini-fab color=\"default\" (click)=\"onClose()\"> <mat-icon>close</mat-icon> </button> <div *ngFor=\"let file of files; let i = index;\" class=\"tzd-image-picker-image\"> <tzd-image-picker-image maxWidth=\"1080\" maxHeight=\"1080\" [debug]=\"debug\" [file]=\"file\" ></tzd-image-picker-image> </div> </div> <form role=\"form\" enctype=\"multipart/form-data\"> <input id=\"files\" name=\"files\" type=\"file\" [multiple]=\"multiple\" #fileUpload hidden=\"true\" (change)=\"updateFilesToLoad($event)\"> </form> <div *ngIf=\"!files\" class=\"text-center\"> <button type=\"button\" mat-mini-fab color=\"accent\" (click)=\"fileUpload.click(); $event.stopPropagation();\"> <mat-icon>add</mat-icon> </button> <button type=\"button\" mat-mini-fab color=\"default\" (click)=\"onClose()\"> <mat-icon>close</mat-icon> </button> <div [ngSwitch]=\"multiple ? true : false\"> <p *ngSwitchCase=\"true\">Select one or more images</p> <p *ngSwitchCase=\"false\">Select one image</p> </div> </div> </ng-template> </div> ", }) export class AngularImagePickerComponent implements OnInit { private manipulationLayerObserver; @Input() debug: boolean; @Input() multiple = false; @Input() type: 'raw' | 'blob' = 'raw'; @ViewChild('fileUpload') fileUpload; // The image-picker elements array images generated by the component @ViewChildren(AngularImagePickerImageComponent) manipulatedImages: QueryList<AngularImagePickerImageComponent>; /* ** ngModel compatibility ** Used to two way data bind using [(ngModel)] */ // The internal data model private images: File | FileList | string | string[]; files: File | FileList | string | string[]; // use file input or show image changeImageMode: boolean; // initial image passed to ngModule initialModelImages; // Used to trigger change event @Output() close: EventEmitter<any> = new EventEmitter<any>(); // Get accessor get value(): File | FileList | string | string[] { return this.images; }; // Set accessor including call the onchange callback set value(v: File | FileList | string | string[]) { if (v !== this.images) { this.images = v; this.onChangeCallback(v); } } constructor() { } ngOnInit() { this.resetComponent(); } // Placeholders for the callbacks which are later provided by the Control Value Accessor private onTouchedCallback = () => {}; // Placeholders for the callbacks which are later provided by the Control Value Accessor private onChangeCallback = (a: any) => {}; // Set touched on blur onBlur() { this.onTouchedCallback(); } // From ControlValueAccessor interface writeValue(value: any) { if (value && value !== this.initialModelImages) { if (this.multiple) { this.initialModelImages = Array.isArray(value) ? value : [value]; } else { this.initialModelImages = value; } } } // From ControlValueAccessor interface registerOnChange(fn: any) { this.onChangeCallback = fn; } // From ControlValueAccessor interface registerOnTouched(fn: any) { this.onTouchedCallback = fn; } onValueChanged(event: any) { this.value = event.toString(); } /* ** Class Methods ** Private and public methods used by the component */ onClose(images?) { this.resetComponent(); this.changeImageMode = false; this.close.emit(images); } // this methos is called by the html when the input file changes updateFilesToLoad($event): void { this.files = $event.target.files; this.refreshManipulationLayerObserver(); } private resetComponent() { if (this.fileUpload) { this.fileUpload.nativeElement.value = ''; } this.files = undefined; this.value = this.initialModelImages || undefined; } private refreshValue = () => { let images; const manipulatedImages = this.manipulatedImages.toArray(); if (this.type === 'blob') { if (this.multiple) { images = manipulatedImages.map(image => image.imageAfterBase64); } else { images = manipulatedImages[0].imageAfterBase64; } } else { if (this.multiple) { images = manipulatedImages.map(image => image.fileAfter); } else { images = manipulatedImages[0].fileAfter; } } this.value = images; } private refreshManipulationLayerObserver() { if (this.manipulatedImages) { if (this.manipulationLayerObserver) { this.manipulationLayerObserver.unsubscribe(); } this.manipulationLayerObserver = this.manipulatedImages.changes.subscribe(() => { this.manipulatedImages.toArray().forEach((image: AngularImagePickerImageComponent) => { image.value.subscribe(this.refreshValue); }); }); } } }